diff options
author | YimingWu <xp8110@outlook.com> | 2020-06-04 13:57:28 +0300 |
---|---|---|
committer | YimingWu <xp8110@outlook.com> | 2020-06-04 13:57:28 +0300 |
commit | bfbf0bb7f7a0191b65fc724d5dfea225e6293c6b (patch) | |
tree | 042f37d28c9e1cf0ce5a0fb4fd4235288f62d36e | |
parent | 3b52dfe549f0c2fca7e0cd499b85fb098e9b4da9 (diff) | |
parent | 78017916f7c7a8ec8907c9b993214ff8ec3c3557 (diff) |
Merge remote-tracking branch 'origin/master' into temp-lanpr-reviewtemp-lanpr-review
# Conflicts:
# release/datafiles/locale
# release/scripts/addons
290 files changed, 7131 insertions, 6599 deletions
diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake index d05a06c9518..9acafe8f8e6 100644 --- a/build_files/build_environment/cmake/harvest.cmake +++ b/build_files/build_environment/cmake/harvest.cmake @@ -31,10 +31,6 @@ if(BUILD_MODE STREQUAL Release) COMMAND # jpeg rename libfile + copy include ${CMAKE_COMMAND} -E copy ${LIBDIR}/jpg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib && ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpg/include/ ${HARVEST_TARGET}/jpeg/include/ && - # OpenImageIO - ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/include ${HARVEST_TARGET}/OpenImageIO/include && - ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/lib ${HARVEST_TARGET}/OpenImageIO/lib && - ${CMAKE_COMMAND} -E copy ${LIBDIR}/OpenImageIO/bin/idiff.exe ${HARVEST_TARGET}/OpenImageIO/bin/idiff.exe && # png ${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static.lib ${HARVEST_TARGET}/png/lib/libpng.lib && ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ && @@ -55,9 +51,7 @@ endif() if(BUILD_MODE STREQUAL Debug) add_custom_target(Harvest_Debug_Results - # OpenImageIO - COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_d.lib && - ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO_Util.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_Util_d.lib && + COMMAND # hdf5 ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hdf5/lib ${HARVEST_TARGET}/hdf5/lib && DEPENDS Package_Python diff --git a/build_files/build_environment/cmake/jpeg.cmake b/build_files/build_environment/cmake/jpeg.cmake index 0d611219353..e0200d84897 100644 --- a/build_files/build_environment/cmake/jpeg.cmake +++ b/build_files/build_environment/cmake/jpeg.cmake @@ -42,20 +42,17 @@ if(WIN32) set(JPEG_LIBRARY jpeg-staticd${LIBEXT}) endif() else(WIN32) - # autoconf for unix - if(APPLE) - set(JPEG_EXTRA_ARGS --host x86_64-apple-darwin --with-jpeg8) - else() - set(JPEG_EXTRA_ARGS --with-jpeg8) - endif() + # cmake for unix + set(JPEG_EXTRA_ARGS + -DWITH_JPEG8=ON + -DENABLE_STATIC=ON + -DENABLE_SHARED=OFF + -DCMAKE_INSTALL_LIBDIR=${LIBDIR}/jpg/lib) ExternalProject_Add(external_jpeg URL ${JPEG_URI} DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH MD5=${JPEG_HASH} - CONFIGURE_COMMAND ${CONFIGURE_ENV} && autoreconf -fiv && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/jpg NASM=yasm ${JPEG_EXTRA_ARGS} - BUILD_IN_SOURCE 1 - BUILD_COMMAND ${CONFIGURE_ENV} && make install PREFIX ${BUILD_DIR}/jpg CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/jpg ${DEFAULT_CMAKE_FLAGS} ${JPEG_EXTRA_ARGS} INSTALL_DIR ${LIBDIR}/jpg diff --git a/build_files/build_environment/cmake/openimageio.cmake b/build_files/build_environment/cmake/openimageio.cmake index 27e04a1f1d1..6ff238468fb 100644 --- a/build_files/build_environment/cmake/openimageio.cmake +++ b/build_files/build_environment/cmake/openimageio.cmake @@ -32,7 +32,7 @@ endif() if(WIN32) set(PNG_LIBNAME libpng16_static${LIBEXT}) - set(OIIO_SIMD_FLAGS -DUSE_SIMD=sse2 -DOPJ_STATIC=1) + set(OIIO_SIMD_FLAGS -DUSE_SIMD=sse2) set(OPENJPEG_POSTFIX _msvc) else() set(PNG_LIBNAME libpng${LIBEXT}) @@ -49,23 +49,17 @@ endif() if(MSVC) set(OPENJPEG_FLAGS - -DOPENJPEG_HOME=${LIBDIR}/openjpeg_msvc - -DOPENJPEG_INCLUDE_DIR=${LIBDIR}/openjpeg_msvc/include/openjpeg-${OPENJPEG_SHORT_VERSION} - -DOPENJPEG_LIBRARY=${LIBDIR}/openjpeg_msvc/lib/openjp2${LIBEXT} - -DOPENJPEG_LIBRARY_DEBUG=${LIBDIR}/openjpeg_msvc/lib/openjp2${LIBEXT} + -DOpenJpeg_ROOT=${LIBDIR}/openjpeg_msvc ) else() set(OPENJPEG_FLAGS - -DOPENJPEG_INCLUDE_DIR=${LIBDIR}/openjpeg/include/openjpeg-${OPENJPEG_SHORT_VERSION} - -DOPENJPEG_LIBRARY=${LIBDIR}/openjpeg/lib/${OPENJPEG_LIBRARY} + -DOpenJpeg_ROOT=${LIBDIR}/openjpeg ) endif() set(OPENIMAGEIO_EXTRA_ARGS - -DBUILDSTATIC=ON + -DBUILD_SHARED_LIBS=OFF ${OPENIMAGEIO_LINKSTATIC} - -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/openexr/ - -DOPENEXR_ILMIMF_LIBRARIES=${LIBDIR}/openexr/lib/IlmImf${OPENEXR_VERSION_POSTFIX}${LIBEXT} -DBoost_COMPILER:STRING=${BOOST_COMPILER_STRING} -DBoost_USE_MULTITHREADED=ON -DBoost_USE_STATIC_LIBS=ON @@ -74,6 +68,14 @@ set(OPENIMAGEIO_EXTRA_ARGS -DBOOST_LIBRARYDIR=${LIBDIR}/boost/lib/ -DBoost_NO_SYSTEM_PATHS=ON -OIIO_BUILD_CPP11=ON + -DUSE_LIBSQUISH=OFF + -DUSE_QT5=OFF + -DUSE_NUKE=OFF + -DUSE_OPENVDB=OFF + -DUSE_BZIP2=OFF + -DUSE_FREETYPE=OFF + -DUSE_DCMTK=OFF + -DUSE_LIBHEIF=OFF -DUSE_OPENGL=OFF -DUSE_TBB=OFF -DUSE_FIELD3D=OFF @@ -81,15 +83,12 @@ set(OPENIMAGEIO_EXTRA_ARGS -DUSE_PYTHON=OFF -DUSE_GIF=OFF -DUSE_OPENCV=OFF - -DUSE_OPENSSL=OFF -DUSE_OPENJPEG=ON -DUSE_FFMPEG=OFF -DUSE_PTEX=OFF -DUSE_FREETYPE=OFF -DUSE_LIBRAW=OFF - -DUSE_PYTHON=OFF - -DUSE_PYTHON3=OFF - -DUSE_OCIO=OFF + -DUSE_OPENCOLORIO=OFF -DUSE_WEBP=${WITH_WEBP} -DOIIO_BUILD_TOOLS=${OIIO_TOOLS} -DOIIO_BUILD_TESTS=OFF @@ -103,17 +102,13 @@ set(OPENIMAGEIO_EXTRA_ARGS -DJPEG_LIBRARY=${LIBDIR}/jpg/lib/${JPEG_LIBRARY} -DJPEG_INCLUDE_DIR=${LIBDIR}/jpg/include ${OPENJPEG_FLAGS} - -DOCIO_PATH=${LIBDIR}/opencolorio/ -DOpenEXR_USE_STATIC_LIBS=On - -DOPENEXR_HOME=${LIBDIR}/openexr/ - -DILMBASE_INCLUDE_PATH=${LIBDIR}/openexr/ - -DILMBASE_PACKAGE_PREFIX=${LIBDIR}/openexr/ -DILMBASE_INCLUDE_DIR=${LIBDIR}/openexr/include/ + -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/ -DOPENEXR_HALF_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}Half${OPENEXR_VERSION_POSTFIX}${LIBEXT} -DOPENEXR_IMATH_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}Imath${OPENEXR_VERSION_POSTFIX}${LIBEXT} -DOPENEXR_ILMTHREAD_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmThread${OPENEXR_VERSION_POSTFIX}${LIBEXT} -DOPENEXR_IEX_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}Iex${OPENEXR_VERSION_POSTFIX}${LIBEXT} - -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/ -DOPENEXR_ILMIMF_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf${OPENEXR_VERSION_POSTFIX}${LIBEXT} -DSTOP_ON_WARNING=OFF ${WEBP_FLAGS} @@ -125,27 +120,38 @@ ExternalProject_Add(external_openimageio DOWNLOAD_DIR ${DOWNLOAD_DIR} URL_HASH MD5=${OPENIMAGEIO_HASH} PREFIX ${BUILD_DIR}/openimageio - PATCH_COMMAND - ${PATCH_CMD} -p 0 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/src/include < ${PATCH_DIR}/openimageio_gdi.diff && - ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio_static_libs.diff + PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio.diff CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openimageio ${DEFAULT_CMAKE_FLAGS} ${OPENIMAGEIO_EXTRA_ARGS} INSTALL_DIR ${LIBDIR}/openimageio ) add_dependencies( external_openimageio - external_png external_zlib + external_png + external_zlib external_openexr external_jpeg external_boost external_tiff - external_opencolorio external_openjpeg${OPENJPEG_POSTFIX} ${WEBP_DEP} ) -if(NOT WIN32) - add_dependencies( - external_openimageio - external_opencolorio_extra - ) + +if(WIN32) + if(BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_openimageio after_install + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/include ${HARVEST_TARGET}/OpenImageIO/include + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/lib ${HARVEST_TARGET}/OpenImageIO/lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/OpenImageIO/bin/idiff.exe ${HARVEST_TARGET}/OpenImageIO/bin/idiff.exe + + DEPENDEES install + ) + endif() + if(BUILD_MODE STREQUAL Debug) + ExternalProject_Add_Step(external_openimageio after_install + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_d.lib + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO_Util.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_Util_d.lib + DEPENDEES install + ) + endif() endif() diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake index 2bf32b77ce9..8dd3c25b88b 100644 --- a/build_files/build_environment/cmake/png.cmake +++ b/build_files/build_environment/cmake/png.cmake @@ -25,7 +25,7 @@ set(PNG_EXTRA_ARGS ExternalProject_Add(external_png URL ${PNG_URI} DOWNLOAD_DIR ${DOWNLOAD_DIR} - URL_HASH MD5=${PNG_HASH} + URL_HASH SHA256=${PNG_HASH} PREFIX ${BUILD_DIR}/png CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/png ${DEFAULT_CMAKE_FLAGS} ${PNG_EXTRA_ARGS} INSTALL_DIR ${LIBDIR}/png diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index 70c4b0948b3..c1dcf98318c 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -24,13 +24,13 @@ set(OPENAL_VERSION 1.20.1) set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2) set(OPENAL_HASH 556695068ce8375b89986083d810fd35) -set(PNG_VERSION 1.6.35) +set(PNG_VERSION 1.6.37) set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.xz) -set(PNG_HASH 678b7e696a62a193ed3503b04bf449d6) +set(PNG_HASH 505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca) -set(JPEG_VERSION 1.5.3) +set(JPEG_VERSION 2.0.4) set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz) -set(JPEG_HASH 5b7549d440b86c98a517355c102d155e) +set(JPEG_HASH 44c43e4a9fb352f47090804529317c88) set(BOOST_VERSION 1.70.0) set(BOOST_VERSION_NODOTS 1_70_0) @@ -113,9 +113,9 @@ set(OPENCOLLADA_VERSION v1.6.68) set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz) set(OPENCOLLADA_HASH ee7dae874019fea7be11613d07567493) -set(OPENCOLORIO_VERSION 1.1.0) -set(OPENCOLORIO_URI https://github.com/imageworks/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz) -set(OPENCOLORIO_HASH 802d8f5b1d1fe316ec5f76511aa611b8) +set(OPENCOLORIO_VERSION 1.1.1) +set(OPENCOLORIO_URI https://github.com/AcademySoftwareFoundation/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz) +set(OPENCOLORIO_HASH 23d8b9ac81599305539a5a8674b94a3d) set(LLVM_VERSION 9.0.1) set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz) @@ -127,17 +127,17 @@ set(CLANG_HASH 13468e4a44940efef1b75e8641752f90) set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/openmp-${LLVM_VERSION}.src.tar.xz) set(OPENMP_HASH 6eade16057edbdecb3c4eef9daa2bfcf) -set(OPENIMAGEIO_VERSION 1.8.13) +set(OPENIMAGEIO_VERSION 2.1.15.0) set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/Release-${OPENIMAGEIO_VERSION}.tar.gz) -set(OPENIMAGEIO_HASH f5526c3c9878029ee900d84856683f93) +set(OPENIMAGEIO_HASH f03aa5e3ac4795af04771ee4146e9832) -set(TIFF_VERSION 4.0.9) +set(TIFF_VERSION 4.1.0) set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz) -set(TIFF_HASH 54bad211279cc93eb4fca31ba9bfdc79) +set(TIFF_HASH 2165e7aba557463acc0664e71a3ed424) -set(OSL_VERSION 1.10.9) +set(OSL_VERSION 1.10.10) set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz) -set(OSL_HASH a94f1e8506f7e8f5e993653de5c5fa00) +set(OSL_HASH 00dec08a93c8084e53848b9ad047889f) set(PYTHON_VERSION 3.7.4) set(PYTHON_SHORT_VERSION 3.7) @@ -199,12 +199,10 @@ set(XVIDCORE_VERSION 1.3.7) set(XVIDCORE_URI https://downloads.xvid.com/downloads/xvidcore-${XVIDCORE_VERSION}.tar.gz) set(XVIDCORE_HASH abbdcbd39555691dd1c9b4d08f0a031376a3b211652c0d8b3b8aa9be1303ce2d) -# This has to be in sync with the version in blenders /extern folder. -set(OPENJPEG_VERSION 2.3.0) +set(OPENJPEG_VERSION 2.3.1) set(OPENJPEG_SHORT_VERSION 2.3) -# Use slightly newer commit after release which includes a cmake fix -set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/66297f07a43.zip) -set(OPENJPEG_HASH 8242b18d908c7c42174e4231a741cfa7ce7c26b6ed5c9644feb9df7b3054310b) +set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz) +set(OPENJPEG_HASH 63f5a4713ecafc86de51bfad89cc07bb788e9bba24ebbf0c4ca637621aadb6a9) set(FFMPEG_VERSION 4.2.3) set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2) @@ -214,9 +212,9 @@ set(FFTW_VERSION 3.3.8) set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz) set(FFTW_HASH 8aac833c943d8e90d51b697b27d4384d) -set(ICONV_VERSION 1.15) +set(ICONV_VERSION 1.16) set(ICONV_URI http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz) -set(ICONV_HASH ace8b5f2db42f7b3b3057585e80d9808) +set(ICONV_HASH 7d2a800b952942bb2880efb00cfd524c) set(LAPACK_VERSION 3.6.0) set(LAPACK_URI http://www.netlib.org/lapack/lapack-${LAPACK_VERSION}.tgz) @@ -263,9 +261,9 @@ set(LCMS_VERSION 2.9) set(LCMS_URI https://nchc.dl.sourceforge.net/project/lcms/lcms/${LCMS_VERSION}/lcms2-${LCMS_VERSION}.tar.gz) set(LCMS_HASH 8de1b7724f578d2995c8fdfa35c3ad0e) -set(PUGIXML_VERSION 1.9) -set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v1.9.tar.gz) -set(PUGIXML_HASH 9346ca1dce2c48f1748c12fdac41a714) +set(PUGIXML_VERSION 1.10) +set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz) +set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd) set(FLEXBISON_VERSION 2.5.5) set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison//win_flex_bison-2.5.5.zip) diff --git a/build_files/build_environment/patches/openimageio.diff b/build_files/build_environment/patches/openimageio.diff new file mode 100644 index 00000000000..d05fc1f295f --- /dev/null +++ b/build_files/build_environment/patches/openimageio.diff @@ -0,0 +1,36 @@ +diff -Naur orig/CMakeLists.txt external_openimageio/CMakeLists.txt +--- orig/CMakeLists.txt 2020-05-10 21:43:52 -0600 ++++ external_openimageio/CMakeLists.txt 2020-05-13 17:03:35 -0600 +@@ -170,7 +170,7 @@ + add_subdirectory (src/iinfo) + add_subdirectory (src/maketx) + add_subdirectory (src/oiiotool) +- add_subdirectory (src/testtex) ++ #add_subdirectory (src/testtex) + add_subdirectory (src/iv) + endif () + +diff -Naur orig/src/cmake/compiler.cmake external_openimageio/src/cmake/compiler.cmake +--- orig/src/cmake/compiler.cmake 2020-05-10 21:43:52 -0600 ++++ external_openimageio/src/cmake/compiler.cmake 2020-05-13 17:02:54 -0600 +@@ -172,6 +172,7 @@ + add_definitions (-D_CRT_NONSTDC_NO_WARNINGS) + add_definitions (-D_SCL_SECURE_NO_WARNINGS) + add_definitions (-DJAS_WIN_MSVC_BUILD) ++ add_definitions (-DOPJ_STATIC) + endif (MSVC) + + if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" +diff -Naur orig/src/include/OpenImageIO/platform.h external_openimageio/src/include/OpenImageIO/platform.h +--- orig/src/include/OpenImageIO/platform.h 2020-05-10 21:43:52 -0600 ++++ external_openimageio/src/include/OpenImageIO/platform.h 2020-05-13 17:04:36 -0600 +@@ -41,6 +41,9 @@ + # ifndef NOMINMAX + # define NOMINMAX + # endif ++# ifndef NOGDI ++# define NOGDI ++# endif + # include <windows.h> + #endif + diff --git a/build_files/build_environment/patches/openimageio_gdi.diff b/build_files/build_environment/patches/openimageio_gdi.diff deleted file mode 100644 index af0c90638de..00000000000 --- a/build_files/build_environment/patches/openimageio_gdi.diff +++ /dev/null @@ -1,26 +0,0 @@ -Index: OpenImageIO/osdep.h -=================================================================== ---- OpenImageIO/osdep.h (revision 61595) -+++ OpenImageIO/osdep.h (working copy) -@@ -34,6 +34,7 @@ - # define WIN32_LEAN_AND_MEAN - # define VC_EXTRALEAN - # define NOMINMAX -+# define NOGDI - # include <windows.h> - #endif - -Index: OpenImageIO/platform.h -=================================================================== ---- OpenImageIO/platform.h (revision 61595) -+++ OpenImageIO/platform.h (working copy) -@@ -77,6 +77,9 @@ - # ifndef NOMINMAX - # define NOMINMAX - # endif -+# ifndef NOGDI -+# define NOGDI -+# endif - # include <windows.h> - #endif - diff --git a/build_files/build_environment/patches/openimageio_static_libs.diff b/build_files/build_environment/patches/openimageio_static_libs.diff deleted file mode 100644 index 6a2e58bd139..00000000000 --- a/build_files/build_environment/patches/openimageio_static_libs.diff +++ /dev/null @@ -1,22 +0,0 @@ -diff -Naur external_openimageio.orig/src/cmake/compiler.cmake external_openimageio/src/cmake/compiler.cmake ---- external_openimageio.orig/src/cmake/compiler.cmake 2018-07-31 23:45:19 -0600 -+++ external_openimageio/src/cmake/compiler.cmake 2018-08-16 12:50:12 -0600 -@@ -152,6 +152,7 @@ - add_definitions (-D_CRT_NONSTDC_NO_WARNINGS) - add_definitions (-D_SCL_SECURE_NO_WARNINGS) - add_definitions (-DJAS_WIN_MSVC_BUILD) -+ add_definitions (-DOPJ_STATIC) - endif (MSVC) - - # Use ccache if found ---- external_openimageio.orig/CMakeLists.txt 2018-07-31 23:45:19 -0600 -+++ external_openimageio/CMakeLists.txt 2018-08-17 15:22:56 -0600 -@@ -169,7 +169,7 @@ - add_subdirectory (src/iinfo) - add_subdirectory (src/maketx) - add_subdirectory (src/oiiotool) -- add_subdirectory (src/testtex) -+# add_subdirectory (src/testtex) - add_subdirectory (src/iv) - endif () - diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff index b9b5937ae2b..989800174e2 100644 --- a/build_files/build_environment/patches/osl.diff +++ b/build_files/build_environment/patches/osl.diff @@ -48,3 +48,22 @@ diff -Naur OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp extern size_t LLVM_Util::total_jit_memory_held () +diff -Naur OpenShadingLanguage-Release-1.9.9/CMakeLists.txt external_osl/CMakeLists.txt + --- orig/CMakeLists.txt 2020-01-27 16:22:31 -0700 ++++ external_osl/CMakeLists.txt 2020-05-13 18:04:52 -0600 +@@ -102,10 +102,11 @@ + set (OPTIX_EXTRA_LIBS CACHE STRING "Extra lib targets needed for OptiX") + set (CUDA_TARGET_ARCH "sm_35" CACHE STRING "CUDA GPU architecture (e.g. sm_35)") + +-# set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static") +-# if (USE_OIIO_STATIC) +-# add_definitions ("-DOIIO_STATIC_BUILD=1") +-# endif () ++set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static") ++if (USE_OIIO_STATIC) ++ add_definitions ("-DOIIO_STATIC_BUILD=1") ++ add_definitions ("-DOIIO_STATIC_DEFINE=1") ++endif () + + set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem") + if (OSL_NO_DEFAULT_TEXTURESYSTEM)
\ No newline at end of file diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 57bfe19a5bc..db939b1d00c 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -478,7 +478,7 @@ if(WITH_OPENIMAGEIO) set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0") set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD") set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe") - add_definitions(-DOIIO_STATIC_BUILD) + add_definitions(-DOIIO_STATIC_DEFINE) add_definitions(-DOIIO_NO_SSE=1) endif() diff --git a/doc/python_api/examples/gpu.1.py b/doc/python_api/examples/gpu.1.py index 831349e5430..a014e69c2d2 100644 --- a/doc/python_api/examples/gpu.1.py +++ b/doc/python_api/examples/gpu.1.py @@ -119,4 +119,24 @@ Examples To try these examples, just copy them into Blenders text editor and execute them. To keep the examples relatively small, they just register a draw function that can't easily be removed anymore. Blender has to be restarted in order to delete the draw handlers. + +3D Lines with Single Color +-------------------------- """ + +import bpy +import gpu +from gpu_extras.batch import batch_for_shader + +coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)] +shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') +batch = batch_for_shader(shader, 'LINES', {"pos": coords}) + + +def draw(): + shader.bind() + shader.uniform_float("color", (1, 1, 0, 1)) + batch.draw(shader) + + +bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') diff --git a/doc/python_api/examples/gpu.10.py b/doc/python_api/examples/gpu.10.py index a4db576ecc0..2f255b7127d 100644 --- a/doc/python_api/examples/gpu.10.py +++ b/doc/python_api/examples/gpu.10.py @@ -1,41 +1,65 @@ """ -Rendering the 3D View into a Texture ------------------------------------- +Custom Shader for dotted 3D Line +-------------------------------- -The scene has to have a camera for this example to work. -You could also make this independent of a specific camera, -but Blender does not expose good functions to create view and projection matrices yet. +In this example the arc length (distance to the first point on the line) is calculated in every vertex. +Between the vertex and fragment shader that value is automatically interpolated +for all points that will be visible on the screen. +In the fragment shader the ``sin`` of the arc length is calculated. +Based on the result a decision is made on whether the fragment should be drawn or not. """ import bpy -import bgl import gpu -from gpu_extras.presets import draw_texture_2d +from random import random +from mathutils import Vector +from gpu_extras.batch import batch_for_shader -WIDTH = 512 -HEIGHT = 256 +vertex_shader = ''' + uniform mat4 u_ViewProjectionMatrix; -offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT) + in vec3 position; + in float arcLength; + out float v_ArcLength; -def draw(): - context = bpy.context - scene = context.scene + void main() + { + v_ArcLength = arcLength; + gl_Position = u_ViewProjectionMatrix * vec4(position, 1.0f); + } +''' + +fragment_shader = ''' + uniform float u_Scale; + + in float v_ArcLength; - view_matrix = scene.camera.matrix_world.inverted() + void main() + { + if (step(sin(v_ArcLength * u_Scale), 0.5) == 1) discard; + gl_FragColor = vec4(1.0); + } +''' - projection_matrix = scene.camera.calc_matrix_camera( - context.evaluated_depsgraph_get(), x=WIDTH, y=HEIGHT) +coords = [Vector((random(), random(), random())) * 5 for _ in range(5)] - offscreen.draw_view3d( - scene, - context.view_layer, - context.space_data, - context.region, - view_matrix, - projection_matrix) +arc_lengths = [0] +for a, b in zip(coords[:-1], coords[1:]): + arc_lengths.append(arc_lengths[-1] + (a - b).length) - bgl.glDisable(bgl.GL_DEPTH_TEST) - draw_texture_2d(offscreen.color_texture, (10, 10), WIDTH, HEIGHT) +shader = gpu.types.GPUShader(vertex_shader, fragment_shader) +batch = batch_for_shader( + shader, 'LINE_STRIP', + {"position": coords, "arcLength": arc_lengths}, +) + + +def draw(): + shader.bind() + matrix = bpy.context.region_data.perspective_matrix + shader.uniform_float("u_ViewProjectionMatrix", matrix) + shader.uniform_float("u_Scale", 10) + batch.draw(shader) -bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL') +bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') diff --git a/doc/python_api/examples/gpu.11.py b/doc/python_api/examples/gpu.11.py deleted file mode 100644 index 2f255b7127d..00000000000 --- a/doc/python_api/examples/gpu.11.py +++ /dev/null @@ -1,65 +0,0 @@ -""" -Custom Shader for dotted 3D Line --------------------------------- - -In this example the arc length (distance to the first point on the line) is calculated in every vertex. -Between the vertex and fragment shader that value is automatically interpolated -for all points that will be visible on the screen. -In the fragment shader the ``sin`` of the arc length is calculated. -Based on the result a decision is made on whether the fragment should be drawn or not. -""" -import bpy -import gpu -from random import random -from mathutils import Vector -from gpu_extras.batch import batch_for_shader - -vertex_shader = ''' - uniform mat4 u_ViewProjectionMatrix; - - in vec3 position; - in float arcLength; - - out float v_ArcLength; - - void main() - { - v_ArcLength = arcLength; - gl_Position = u_ViewProjectionMatrix * vec4(position, 1.0f); - } -''' - -fragment_shader = ''' - uniform float u_Scale; - - in float v_ArcLength; - - void main() - { - if (step(sin(v_ArcLength * u_Scale), 0.5) == 1) discard; - gl_FragColor = vec4(1.0); - } -''' - -coords = [Vector((random(), random(), random())) * 5 for _ in range(5)] - -arc_lengths = [0] -for a, b in zip(coords[:-1], coords[1:]): - arc_lengths.append(arc_lengths[-1] + (a - b).length) - -shader = gpu.types.GPUShader(vertex_shader, fragment_shader) -batch = batch_for_shader( - shader, 'LINE_STRIP', - {"position": coords, "arcLength": arc_lengths}, -) - - -def draw(): - shader.bind() - matrix = bpy.context.region_data.perspective_matrix - shader.uniform_float("u_ViewProjectionMatrix", matrix) - shader.uniform_float("u_Scale", 10) - batch.draw(shader) - - -bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') diff --git a/doc/python_api/examples/gpu.2.py b/doc/python_api/examples/gpu.2.py index d1e8ac32589..4bee9acebe3 100644 --- a/doc/python_api/examples/gpu.2.py +++ b/doc/python_api/examples/gpu.2.py @@ -1,19 +1,45 @@ """ -3D Lines with Single Color --------------------------- +Triangle with Custom Shader +--------------------------- """ import bpy import gpu from gpu_extras.batch import batch_for_shader -coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)] -shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') -batch = batch_for_shader(shader, 'LINES', {"pos": coords}) +vertex_shader = ''' + uniform mat4 viewProjectionMatrix; + + in vec3 position; + out vec3 pos; + + void main() + { + pos = position; + gl_Position = viewProjectionMatrix * vec4(position, 1.0f); + } +''' + +fragment_shader = ''' + uniform float brightness; + + in vec3 pos; + + void main() + { + gl_FragColor = vec4(pos * brightness, 1.0); + } +''' + +coords = [(1, 1, 1), (2, 0, 0), (-2, -1, 3)] +shader = gpu.types.GPUShader(vertex_shader, fragment_shader) +batch = batch_for_shader(shader, 'TRIS', {"position": coords}) def draw(): shader.bind() - shader.uniform_float("color", (1, 1, 0, 1)) + matrix = bpy.context.region_data.perspective_matrix + shader.uniform_float("viewProjectionMatrix", matrix) + shader.uniform_float("brightness", 0.5) batch.draw(shader) diff --git a/doc/python_api/examples/gpu.3.py b/doc/python_api/examples/gpu.3.py index 4bee9acebe3..0c86b52bcf5 100644 --- a/doc/python_api/examples/gpu.3.py +++ b/doc/python_api/examples/gpu.3.py @@ -1,45 +1,29 @@ """ -Triangle with Custom Shader ---------------------------- +Wireframe Cube using Index Buffer +--------------------------------- """ import bpy import gpu from gpu_extras.batch import batch_for_shader -vertex_shader = ''' - uniform mat4 viewProjectionMatrix; +coords = ( + (-1, -1, -1), (+1, -1, -1), + (-1, +1, -1), (+1, +1, -1), + (-1, -1, +1), (+1, -1, +1), + (-1, +1, +1), (+1, +1, +1)) - in vec3 position; - out vec3 pos; +indices = ( + (0, 1), (0, 2), (1, 3), (2, 3), + (4, 5), (4, 6), (5, 7), (6, 7), + (0, 4), (1, 5), (2, 6), (3, 7)) - void main() - { - pos = position; - gl_Position = viewProjectionMatrix * vec4(position, 1.0f); - } -''' - -fragment_shader = ''' - uniform float brightness; - - in vec3 pos; - - void main() - { - gl_FragColor = vec4(pos * brightness, 1.0); - } -''' - -coords = [(1, 1, 1), (2, 0, 0), (-2, -1, 3)] -shader = gpu.types.GPUShader(vertex_shader, fragment_shader) -batch = batch_for_shader(shader, 'TRIS', {"position": coords}) +shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') +batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices) def draw(): shader.bind() - matrix = bpy.context.region_data.perspective_matrix - shader.uniform_float("viewProjectionMatrix", matrix) - shader.uniform_float("brightness", 0.5) + shader.uniform_float("color", (1, 0, 0, 1)) batch.draw(shader) diff --git a/doc/python_api/examples/gpu.4.py b/doc/python_api/examples/gpu.4.py index 0c86b52bcf5..e05290a9442 100644 --- a/doc/python_api/examples/gpu.4.py +++ b/doc/python_api/examples/gpu.4.py @@ -1,30 +1,39 @@ """ -Wireframe Cube using Index Buffer ---------------------------------- +Mesh with Random Vertex Colors +------------------------------ """ import bpy import gpu +import bgl +import numpy as np +from random import random from gpu_extras.batch import batch_for_shader -coords = ( - (-1, -1, -1), (+1, -1, -1), - (-1, +1, -1), (+1, +1, -1), - (-1, -1, +1), (+1, -1, +1), - (-1, +1, +1), (+1, +1, +1)) +mesh = bpy.context.active_object.data +mesh.calc_loop_triangles() -indices = ( - (0, 1), (0, 2), (1, 3), (2, 3), - (4, 5), (4, 6), (5, 7), (6, 7), - (0, 4), (1, 5), (2, 6), (3, 7)) +vertices = np.empty((len(mesh.vertices), 3), 'f') +indices = np.empty((len(mesh.loop_triangles), 3), 'i') -shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR') -batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices) +mesh.vertices.foreach_get( + "co", np.reshape(vertices, len(mesh.vertices) * 3)) +mesh.loop_triangles.foreach_get( + "vertices", np.reshape(indices, len(mesh.loop_triangles) * 3)) + +vertex_colors = [(random(), random(), random(), 1) for _ in range(len(mesh.vertices))] + +shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR') +batch = batch_for_shader( + shader, 'TRIS', + {"pos": vertices, "color": vertex_colors}, + indices=indices, +) def draw(): - shader.bind() - shader.uniform_float("color", (1, 0, 0, 1)) + bgl.glEnable(bgl.GL_DEPTH_TEST) batch.draw(shader) + bgl.glDisable(bgl.GL_DEPTH_TEST) bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') diff --git a/doc/python_api/examples/gpu.5.py b/doc/python_api/examples/gpu.5.py index e05290a9442..2edde46a364 100644 --- a/doc/python_api/examples/gpu.5.py +++ b/doc/python_api/examples/gpu.5.py @@ -1,39 +1,26 @@ """ -Mesh with Random Vertex Colors ------------------------------- +2D Rectangle +------------ """ import bpy import gpu -import bgl -import numpy as np -from random import random from gpu_extras.batch import batch_for_shader -mesh = bpy.context.active_object.data -mesh.calc_loop_triangles() +vertices = ( + (100, 100), (300, 100), + (100, 200), (300, 200)) -vertices = np.empty((len(mesh.vertices), 3), 'f') -indices = np.empty((len(mesh.loop_triangles), 3), 'i') +indices = ( + (0, 1, 2), (2, 1, 3)) -mesh.vertices.foreach_get( - "co", np.reshape(vertices, len(mesh.vertices) * 3)) -mesh.loop_triangles.foreach_get( - "vertices", np.reshape(indices, len(mesh.loop_triangles) * 3)) - -vertex_colors = [(random(), random(), random(), 1) for _ in range(len(mesh.vertices))] - -shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR') -batch = batch_for_shader( - shader, 'TRIS', - {"pos": vertices, "color": vertex_colors}, - indices=indices, -) +shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') +batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices) def draw(): - bgl.glEnable(bgl.GL_DEPTH_TEST) + shader.bind() + shader.uniform_float("color", (0, 0.5, 0.5, 1.0)) batch.draw(shader) - bgl.glDisable(bgl.GL_DEPTH_TEST) -bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') +bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL') diff --git a/doc/python_api/examples/gpu.6.py b/doc/python_api/examples/gpu.6.py index 2edde46a364..69af65e163e 100644 --- a/doc/python_api/examples/gpu.6.py +++ b/doc/python_api/examples/gpu.6.py @@ -1,25 +1,36 @@ """ -2D Rectangle ------------- +2D Image +-------- + +To use this example you have to provide an image that should be displayed. """ import bpy import gpu +import bgl from gpu_extras.batch import batch_for_shader -vertices = ( - (100, 100), (300, 100), - (100, 200), (300, 200)) +IMAGE_NAME = "Untitled" +image = bpy.data.images[IMAGE_NAME] -indices = ( - (0, 1, 2), (2, 1, 3)) +shader = gpu.shader.from_builtin('2D_IMAGE') +batch = batch_for_shader( + shader, 'TRI_FAN', + { + "pos": ((100, 100), (200, 100), (200, 200), (100, 200)), + "texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)), + }, +) -shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') -batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices) +if image.gl_load(): + raise Exception() def draw(): + bgl.glActiveTexture(bgl.GL_TEXTURE0) + bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode) + shader.bind() - shader.uniform_float("color", (0, 0.5, 0.5, 1.0)) + shader.uniform_int("image", 0) batch.draw(shader) diff --git a/doc/python_api/examples/gpu.7.py b/doc/python_api/examples/gpu.7.py index 69af65e163e..56cbb93c61a 100644 --- a/doc/python_api/examples/gpu.7.py +++ b/doc/python_api/examples/gpu.7.py @@ -1,37 +1,86 @@ """ -2D Image --------- +Generate a texture using Offscreen Rendering +-------------------------------------------- -To use this example you have to provide an image that should be displayed. +#. Create an :class:`gpu.types.GPUOffScreen` object. +#. Draw some circles into it. +#. Make a new shader for drawing a planar texture in 3D. +#. Draw the generated texture using the new shader. """ import bpy import gpu import bgl +from mathutils import Matrix from gpu_extras.batch import batch_for_shader +from gpu_extras.presets import draw_circle_2d -IMAGE_NAME = "Untitled" -image = bpy.data.images[IMAGE_NAME] +# Create and fill offscreen +########################################## -shader = gpu.shader.from_builtin('2D_IMAGE') +offscreen = gpu.types.GPUOffScreen(512, 512) + +with offscreen.bind(): + bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) + with gpu.matrix.push_pop(): + # reset matrices -> use normalized device coordinates [-1, 1] + gpu.matrix.load_matrix(Matrix.Identity(4)) + gpu.matrix.load_projection_matrix(Matrix.Identity(4)) + + amount = 10 + for i in range(-amount, amount + 1): + x_pos = i / amount + draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, 200) + + +# Drawing the generated texture in 3D space +############################################# + +vertex_shader = ''' + uniform mat4 modelMatrix; + uniform mat4 viewProjectionMatrix; + + in vec2 position; + in vec2 uv; + + out vec2 uvInterp; + + void main() + { + uvInterp = uv; + gl_Position = viewProjectionMatrix * modelMatrix * vec4(position, 0.0, 1.0); + } +''' + +fragment_shader = ''' + uniform sampler2D image; + + in vec2 uvInterp; + + void main() + { + gl_FragColor = texture(image, uvInterp); + } +''' + +shader = gpu.types.GPUShader(vertex_shader, fragment_shader) batch = batch_for_shader( shader, 'TRI_FAN', { - "pos": ((100, 100), (200, 100), (200, 200), (100, 200)), - "texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)), + "position": ((-1, -1), (1, -1), (1, 1), (-1, 1)), + "uv": ((0, 0), (1, 0), (1, 1), (0, 1)), }, ) -if image.gl_load(): - raise Exception() - def draw(): bgl.glActiveTexture(bgl.GL_TEXTURE0) - bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode) + bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture) shader.bind() - shader.uniform_int("image", 0) + shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4)) + shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix) + shader.uniform_float("image", 0) batch.draw(shader) -bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL') +bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') diff --git a/doc/python_api/examples/gpu.8.py b/doc/python_api/examples/gpu.8.py index 56cbb93c61a..470bd8a2dad 100644 --- a/doc/python_api/examples/gpu.8.py +++ b/doc/python_api/examples/gpu.8.py @@ -1,23 +1,28 @@ """ -Generate a texture using Offscreen Rendering --------------------------------------------- +Copy Offscreen Rendering result back to RAM +------------------------------------------- -#. Create an :class:`gpu.types.GPUOffScreen` object. -#. Draw some circles into it. -#. Make a new shader for drawing a planar texture in 3D. -#. Draw the generated texture using the new shader. +This will create a new image with the given name. +If it already exists, it will override the existing one. + +Currently almost all of the execution time is spent in the last line. +In the future this will hopefully be solved by implementing the Python buffer protocol +for :class:`bgl.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``). """ import bpy import gpu import bgl +import random from mathutils import Matrix -from gpu_extras.batch import batch_for_shader from gpu_extras.presets import draw_circle_2d -# Create and fill offscreen -########################################## +IMAGE_NAME = "Generated Image" +WIDTH = 512 +HEIGHT = 512 +RING_AMOUNT = 10 + -offscreen = gpu.types.GPUOffScreen(512, 512) +offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT) with offscreen.bind(): bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) @@ -26,61 +31,20 @@ with offscreen.bind(): gpu.matrix.load_matrix(Matrix.Identity(4)) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) - amount = 10 - for i in range(-amount, amount + 1): - x_pos = i / amount - draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, 200) - - -# Drawing the generated texture in 3D space -############################################# - -vertex_shader = ''' - uniform mat4 modelMatrix; - uniform mat4 viewProjectionMatrix; - - in vec2 position; - in vec2 uv; - - out vec2 uvInterp; - - void main() - { - uvInterp = uv; - gl_Position = viewProjectionMatrix * modelMatrix * vec4(position, 0.0, 1.0); - } -''' - -fragment_shader = ''' - uniform sampler2D image; - - in vec2 uvInterp; - - void main() - { - gl_FragColor = texture(image, uvInterp); - } -''' - -shader = gpu.types.GPUShader(vertex_shader, fragment_shader) -batch = batch_for_shader( - shader, 'TRI_FAN', - { - "position": ((-1, -1), (1, -1), (1, 1), (-1, 1)), - "uv": ((0, 0), (1, 0), (1, 1), (0, 1)), - }, -) - + for i in range(RING_AMOUNT): + draw_circle_2d( + (random.uniform(-1, 1), random.uniform(-1, 1)), + (1, 1, 1, 1), random.uniform(0.1, 1), 20) -def draw(): - bgl.glActiveTexture(bgl.GL_TEXTURE0) - bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture) + buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4) + bgl.glReadBuffer(bgl.GL_BACK) + bgl.glReadPixels(0, 0, WIDTH, HEIGHT, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) - shader.bind() - shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4)) - shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix) - shader.uniform_float("image", 0) - batch.draw(shader) +offscreen.free() -bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW') +if not IMAGE_NAME in bpy.data.images: + bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT) +image = bpy.data.images[IMAGE_NAME] +image.scale(WIDTH, HEIGHT) +image.pixels = [v / 255 for v in buffer] diff --git a/doc/python_api/examples/gpu.9.py b/doc/python_api/examples/gpu.9.py index 470bd8a2dad..a4db576ecc0 100644 --- a/doc/python_api/examples/gpu.9.py +++ b/doc/python_api/examples/gpu.9.py @@ -1,50 +1,41 @@ """ -Copy Offscreen Rendering result back to RAM -------------------------------------------- +Rendering the 3D View into a Texture +------------------------------------ -This will create a new image with the given name. -If it already exists, it will override the existing one. - -Currently almost all of the execution time is spent in the last line. -In the future this will hopefully be solved by implementing the Python buffer protocol -for :class:`bgl.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``). +The scene has to have a camera for this example to work. +You could also make this independent of a specific camera, +but Blender does not expose good functions to create view and projection matrices yet. """ import bpy -import gpu import bgl -import random -from mathutils import Matrix -from gpu_extras.presets import draw_circle_2d +import gpu +from gpu_extras.presets import draw_texture_2d -IMAGE_NAME = "Generated Image" WIDTH = 512 -HEIGHT = 512 -RING_AMOUNT = 10 - +HEIGHT = 256 offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT) -with offscreen.bind(): - bgl.glClear(bgl.GL_COLOR_BUFFER_BIT) - with gpu.matrix.push_pop(): - # reset matrices -> use normalized device coordinates [-1, 1] - gpu.matrix.load_matrix(Matrix.Identity(4)) - gpu.matrix.load_projection_matrix(Matrix.Identity(4)) - for i in range(RING_AMOUNT): - draw_circle_2d( - (random.uniform(-1, 1), random.uniform(-1, 1)), - (1, 1, 1, 1), random.uniform(0.1, 1), 20) +def draw(): + context = bpy.context + scene = context.scene + + view_matrix = scene.camera.matrix_world.inverted() + + projection_matrix = scene.camera.calc_matrix_camera( + context.evaluated_depsgraph_get(), x=WIDTH, y=HEIGHT) - buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4) - bgl.glReadBuffer(bgl.GL_BACK) - bgl.glReadPixels(0, 0, WIDTH, HEIGHT, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer) + offscreen.draw_view3d( + scene, + context.view_layer, + context.space_data, + context.region, + view_matrix, + projection_matrix) -offscreen.free() + bgl.glDisable(bgl.GL_DEPTH_TEST) + draw_texture_2d(offscreen.color_texture, (10, 10), WIDTH, HEIGHT) -if not IMAGE_NAME in bpy.data.images: - bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT) -image = bpy.data.images[IMAGE_NAME] -image.scale(WIDTH, HEIGHT) -image.pixels = [v / 255 for v in buffer] +bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL') diff --git a/doc/python_api/sphinx_doc_update.py b/doc/python_api/sphinx_doc_update.py index 6b24f4c4c09..4495fca9274 100755 --- a/doc/python_api/sphinx_doc_update.py +++ b/doc/python_api/sphinx_doc_update.py @@ -128,7 +128,7 @@ def main(): " f.write('%d\\n' % is_beta)\n" " f.write('%s\\n' % branch)\n" " f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1]))\n" - " f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1]))\n" + " f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1])\n" " if (is_release or is_beta) else '%s\\n' % branch)\n" " f.write('%d_%d' % (bpy.app.version[0], bpy.app.version[1]))\n" ) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index c91e210bbd8..da18ac7c693 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1205,6 +1205,13 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): default=1.0, ) + shadow_terminator_offset: FloatProperty( + name="Shadow Terminator Offset", + description="Push the shadow terminator towards the light to hide artifacts on low poly geometry", + min=0.0, max=1.0, + default=0.0, + ) + is_shadow_catcher: BoolProperty( name="Shadow Catcher", description="Only render shadows on this object, for compositing renders into real footage", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index a15daee706f..78a44881743 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1209,6 +1209,27 @@ def has_geometry_visibility(ob): return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT'}) or (ob.instance_type == 'COLLECTION' and ob.instance_collection)) +class CYCLES_OBJECT_PT_shading(CyclesButtonsPanel, Panel): + bl_label = "Shading" + bl_context = "object" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + return CyclesButtonsPanel.poll(context) and (context.object) + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False) + layout = self.layout + ob = context.object + cob = ob.cycles + + if has_geometry_visibility(ob): + col = flow.column() + col.prop(cob, "shadow_terminator_offset") class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): bl_label = "Visibility" @@ -1367,7 +1388,7 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel): col.separator() if light.type in {'POINT', 'SPOT'}: - col.prop(light, "shadow_soft_size", text="Size") + col.prop(light, "shadow_soft_size", text="Radius") elif light.type == 'SUN': col.prop(light, "angle") elif light.type == 'AREA': @@ -2268,6 +2289,7 @@ classes = ( CYCLES_CAMERA_PT_dof_aperture, CYCLES_PT_context_material, CYCLES_OBJECT_PT_motion_blur, + CYCLES_OBJECT_PT_shading, CYCLES_OBJECT_PT_visibility, CYCLES_OBJECT_PT_visibility_ray_visibility, CYCLES_OBJECT_PT_visibility_culling, diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index a461982a538..c28586d0f63 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -238,6 +238,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, object_updated = true; } + float shadow_terminator_offset = get_float(cobject, "shadow_terminator_offset"); + if (shadow_terminator_offset != object->shadow_terminator_offset) { + object->shadow_terminator_offset = shadow_terminator_offset; + object_updated = true; + } + /* sync the asset name for Cryptomatte */ BL::Object parent = b_ob.parent(); ustring parent_name; diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h index b3992c03a9a..9b9df883b62 100644 --- a/intern/cycles/kernel/bvh/bvh.h +++ b/intern/cycles/kernel/bvh/bvh.h @@ -300,7 +300,9 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg, // Is set to zero on miss or if ray is aborted, so can be used as return value uint p5 = max_hits; - local_isect->num_hits = 0; // Initialize hit count to zero + if (local_isect) { + local_isect->num_hits = 0; // Initialize hit count to zero + } optixTrace(scene_intersect_valid(ray) ? kernel_data.bvh.scene : 0, ray->P, ray->D, @@ -323,7 +325,9 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg, return p5; # else /* __KERNEL_OPTIX__ */ if (!scene_intersect_valid(ray)) { - local_isect->num_hits = 0; + if (local_isect) { + local_isect->num_hits = 0; + } return false; } diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index dc80e67a891..4cc61e8ee71 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -97,6 +97,18 @@ ccl_device_inline float bump_shadowing_term(float3 Ng, float3 N, float3 I) return -g2 * g + g2 + g; } +/* Shadow terminator workaround, taken from Appleseed. + * Original code is under the MIT License + * Copyright (c) 2019 Francois Beaune, The appleseedhq Organization */ +ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multiplier) +{ + cos_in = min(cos_in, 1.0f); + + const float angle = fast_acosf(cos_in); + const float val = max(cosf(angle * frequency_multiplier), 0.0f) / cos_in; + return val; +} + ccl_device_inline int bsdf_sample(KernelGlobals *kg, ShaderData *sd, const ShaderClosure *sc, @@ -444,9 +456,17 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg, } } } - else if (label & LABEL_DIFFUSE) { - if (!isequal_float3(sc->N, sd->N)) { - *eval *= bump_shadowing_term((label & LABEL_TRANSMIT) ? -sd->N : sd->N, sc->N, *omega_in); + else { + /* Shadow terminator offset. */ + const float frequency_multiplier = + kernel_tex_fetch(__objects, sd->object).shadow_terminator_offset; + if (frequency_multiplier > 1.0f) { + *eval *= shift_cos_in(dot(*omega_in, sc->N), frequency_multiplier); + } + if (label & LABEL_DIFFUSE) { + if (!isequal_float3(sc->N, sd->N)) { + *eval *= bump_shadowing_term((label & LABEL_TRANSMIT) ? -sd->N : sd->N, sc->N, *omega_in); + } } } @@ -561,6 +581,12 @@ ccl_device_inline eval *= bump_shadowing_term(sd->N, sc->N, omega_in); } } + /* Shadow terminator offset. */ + const float frequency_multiplier = + kernel_tex_fetch(__objects, sd->object).shadow_terminator_offset; + if (frequency_multiplier > 1.0f) { + eval *= shift_cos_in(dot(omega_in, sc->N), frequency_multiplier); + } } else { switch (sc->type) { diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 62ce04ba48f..445cf9eb44b 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -441,8 +441,22 @@ ccl_device_inline float camera_distance(KernelGlobals *kg, float3 P) float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z); return fabsf(dot((P - camP), camD)); } - else + else { return len(P - camP); + } +} + +ccl_device_inline float camera_z_depth(KernelGlobals *kg, float3 P) +{ + if (kernel_data.cam.type != CAMERA_PANORAMA) { + Transform worldtocamera = kernel_data.cam.worldtocamera; + return transform_point(&worldtocamera, P).z; + } + else { + Transform cameratoworld = kernel_data.cam.cameratoworld; + float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w); + return len(P - camP); + } } ccl_device_inline float3 camera_direction_from_point(KernelGlobals *kg, float3 P) diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index d918abed381..04472212d0c 100644 --- a/intern/cycles/kernel/kernel_light.h +++ b/intern/cycles/kernel/kernel_light.h @@ -249,13 +249,13 @@ ccl_device float3 background_map_sample(KernelGlobals *kg, float randu, float ra float u = (index_u + du) / res_x; /* compute pdf */ - float denom = cdf_last_u.x * cdf_last_v.x; float sin_theta = sinf(M_PI_F * v); + float denom = (M_2PI_F * M_PI_F * sin_theta) * cdf_last_u.x * cdf_last_v.x; if (sin_theta == 0.0f || denom == 0.0f) *pdf = 0.0f; else - *pdf = (cdf_u.x * cdf_v.x) / (M_2PI_F * M_PI_F * sin_theta * denom); + *pdf = (cdf_u.x * cdf_v.x) / denom; /* compute direction */ return equirectangular_to_direction(u, v); @@ -284,7 +284,7 @@ ccl_device float background_map_pdf(KernelGlobals *kg, float3 direction) index_v * cdf_width + res_x); float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y); - float denom = cdf_last_u.x * cdf_last_v.x; + float denom = (M_2PI_F * M_PI_F * sin_theta) * cdf_last_u.x * cdf_last_v.x; if (denom == 0.0f) return 0.0f; @@ -294,7 +294,7 @@ ccl_device float background_map_pdf(KernelGlobals *kg, float3 direction) index_v * cdf_width + index_u); float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v); - return (cdf_u.x * cdf_v.x) / (M_2PI_F * M_PI_F * sin_theta * denom); + return (cdf_u.x * cdf_v.x) / denom; } ccl_device_inline bool background_portal_data_fetch_and_check_side( diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index 7437e540a1f..753cf4561b2 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -194,7 +194,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) { if (state->sample == 0) { if (flag & PASSMASK(DEPTH)) { - float depth = camera_distance(kg, sd->P); + float depth = camera_z_depth(kg, sd->P); kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth); } if (flag & PASSMASK(OBJECT_ID)) { diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 304835a1685..630d00a4e71 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1480,6 +1480,9 @@ typedef struct KernelObject { float cryptomatte_object; float cryptomatte_asset; + + float shadow_terminator_offset; + float pad1, pad2, pad3; } KernelObject; static_assert_align(KernelObject, 16); diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index cd19b03ac53..cb7474017fa 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -120,6 +120,7 @@ NODE_DEFINE(Light) SOCKET_VECTOR(dir, "Dir", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_FLOAT(size, "Size", 0.0f); + SOCKET_FLOAT(angle, "Angle", 0.0f); SOCKET_VECTOR(axisu, "Axis U", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_FLOAT(sizeu, "Size U", 1.0f); @@ -183,6 +184,8 @@ LightManager::LightManager() need_update = true; need_update_background = true; use_light_visibility = false; + last_background_enabled = false; + last_background_resolution = 0; } LightManager::~LightManager() @@ -202,7 +205,7 @@ bool LightManager::has_background_light(Scene *scene) return false; } -void LightManager::disable_ineffective_light(Scene *scene) +void LightManager::test_enabled_lights(Scene *scene) { /* Make all lights enabled by default, and perform some preliminary checks * needed for finer-tuning of settings (for example, check whether we've @@ -215,6 +218,9 @@ void LightManager::disable_ineffective_light(Scene *scene) has_background |= light->type == LIGHT_BACKGROUND; } + bool background_enabled = false; + int background_resolution = 0; + if (has_background) { /* Ignore background light if: * - If unsupported on a device @@ -226,9 +232,18 @@ void LightManager::disable_ineffective_light(Scene *scene) foreach (Light *light, scene->lights) { if (light->type == LIGHT_BACKGROUND) { light->is_enabled = !disable_mis; + background_enabled = !disable_mis; + background_resolution = light->map_resolution; } } } + + if (last_background_enabled != background_enabled || + last_background_resolution != background_resolution) { + last_background_enabled = background_enabled; + last_background_resolution = background_resolution; + need_update_background = true; + } } bool LightManager::object_usable_as_light(Object *object) @@ -902,12 +917,13 @@ void LightManager::device_update(Device *device, VLOG(1) << "Total " << scene->lights.size() << " lights."; + /* Detect which lights are enabled, also determins if we need to update the background. */ + test_enabled_lights(scene); + device_free(device, dscene, need_update_background); use_light_visibility = false; - disable_ineffective_light(scene); - device_update_points(device, dscene, scene); if (progress.get_cancel()) return; diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index 1a99b2b76ae..d136e8f1a08 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -112,7 +112,7 @@ class LightManager { * which doesn't contribute to the scene or which is only used for MIS * and scene doesn't need MIS. */ - void disable_ineffective_light(Scene *scene); + void test_enabled_lights(Scene *scene); void device_update_points(Device *device, DeviceScene *dscene, Scene *scene); void device_update_distribution(Device *device, @@ -136,6 +136,9 @@ class LightManager { vector<IESSlot *> ies_slots; thread_mutex ies_mutex; + + bool last_background_enabled; + int last_background_resolution; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 90a1d90019d..61deef4cd76 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -101,6 +101,7 @@ NODE_DEFINE(Object) SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f)); SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f)); SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>()); + SOCKET_FLOAT(shadow_terminator_offset, "Terminator Offset", 0.0f); SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false); @@ -534,6 +535,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0); kobject.cryptomatte_object = util_hash_to_float(hash_name); kobject.cryptomatte_asset = util_hash_to_float(hash_asset); + kobject.shadow_terminator_offset = 1.0f / (1.0f - 0.5f * ob->shadow_terminator_offset); /* Object flag. */ if (ob->use_holdout) { diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 7c84c2de4fb..ac9b4c331f5 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -59,6 +59,7 @@ class Object : public Node { bool hide_on_missing_motion; bool use_holdout; bool is_shadow_catcher; + float shadow_terminator_offset; float3 dupli_generated; float2 dupli_uv; diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h index 2d09326d2ca..f78cc5f5da9 100644 --- a/intern/cycles/util/util_guarded_allocator.h +++ b/intern/cycles/util/util_guarded_allocator.h @@ -18,6 +18,7 @@ #define __UTIL_GUARDED_ALLOCATOR_H__ #include <cstddef> +#include <cstdlib> #include <memory> #ifdef WITH_BLENDER_GUARDEDALLOC diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index 633451feb85..31110694ea6 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1527,7 +1527,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, - const bool /*is_dialog*/, + const bool is_dialog, const GHOST_IWindow *parentWindow) { GHOST_WindowWayland *window = new GHOST_WindowWayland( @@ -1540,6 +1540,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title, state, parentWindow, type, + is_dialog, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive); diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp index 0ea6f5f8ecb..ef02db7abc3 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cpp +++ b/intern/ghost/intern/GHOST_WindowWayland.cpp @@ -39,6 +39,7 @@ struct window_t { bool is_maximised; bool is_fullscreen; bool is_active; + bool is_dialog; int32_t width, height; }; @@ -144,6 +145,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, GHOST_TWindowState state, const GHOST_IWindow *parentWindow, GHOST_TDrawingContextType type, + const bool is_dialog, const bool stereoVisual, const bool exclusive) : GHOST_Window(width, height, state, stereoVisual, exclusive), @@ -155,6 +157,8 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system, w->width = int32_t(width); w->height = int32_t(height); + w->is_dialog = is_dialog; + /* Window surfaces. */ w->surface = wl_compositor_create_surface(m_system->compositor()); w->egl_window = wl_egl_window_create(w->surface, int(width), int(height)); @@ -376,6 +380,11 @@ GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const return GHOST_kSuccess; } +bool GHOST_WindowWayland::isDialog() const +{ + return w->is_dialog; +} + /** * \param type The type of rendering context create. * \return Indication of success. diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h index 39c35f77d7d..23e55fcd6e4 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.h +++ b/intern/ghost/intern/GHOST_WindowWayland.h @@ -42,6 +42,7 @@ class GHOST_WindowWayland : public GHOST_Window { GHOST_TWindowState state, const GHOST_IWindow *parentWindow, GHOST_TDrawingContextType type, + const bool is_dialog, const bool stereoVisual, const bool exclusive); @@ -106,6 +107,8 @@ class GHOST_WindowWayland : public GHOST_Window { GHOST_TSuccess endFullScreen() const override; + bool isDialog() const override; + private: GHOST_SystemWayland *m_system; struct window_t *w; diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index df6adc8f34b..43416f734c5 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -263,19 +263,20 @@ static void updateGLSLShader(OCIO_GLSLShader *shader, shader->curve_mapping_loc = glGetUniformLocation(shader->program, "curve_mapping"); glUseProgram(shader->program); - /* Set texture bind point uniform once. This is saved by the shader. */ - glUniform1i(glGetUniformLocation(shader->program, "image_texture"), 0); - glUniform1i(glGetUniformLocation(shader->program, "lut3d_texture"), 2); - glUniform1i(glGetUniformLocation(shader->program, "lut3d_display_texture"), 3); - glUniform1i(glGetUniformLocation(shader->program, "curve_mapping_texture"), 4); + + /* TODO(fclem) Remove this. Make caller always assume viewport space and + * specify texco via vertex attribs. */ + shader->interface = GPU_shaderinterface_create(shader->program); /* Set UBO binding location. */ GLuint index = glGetUniformBlockIndex(shader->program, "OCIO_GLSLCurveMappingParameters"); glUniformBlockBinding(shader->program, index, UBO_BIND_LOC); - /* TODO(fclem) Remove this. Make caller always assume viewport space and - * specify texco via vertex attribs. */ - shader->interface = GPU_shaderinterface_create(shader->program); + /* Set texture bind point uniform once. This is saved by the shader. */ + glUniform1i(glGetUniformLocation(shader->program, "image_texture"), 0); + glUniform1i(glGetUniformLocation(shader->program, "lut3d_texture"), 2); + glUniform1i(glGetUniformLocation(shader->program, "lut3d_display_texture"), 3); + glUniform1i(glGetUniformLocation(shader->program, "curve_mapping_texture"), 4); } shader->cacheId = cache_id; diff --git a/release/scripts/modules/bl_app_template_utils.py b/release/scripts/modules/bl_app_template_utils.py index 42467d21580..7db084a9a29 100644 --- a/release/scripts/modules/bl_app_template_utils.py +++ b/release/scripts/modules/bl_app_template_utils.py @@ -68,14 +68,15 @@ def _enable(template_id, *, handle_error=None, ignore_not_found=False): # 1) try import try: mod = import_from_id(template_id, ignore_not_found=ignore_not_found) - if mod is None: - return None - mod.__template_enabled__ = False - _modules[template_id] = mod except Exception as ex: handle_error(ex) return None + _modules[template_id] = mod + if mod is None: + return None + mod.__template_enabled__ = False + # 2) try run the modules register function try: mod.register() @@ -111,9 +112,12 @@ def _disable(template_id, *, handle_error=None): import traceback traceback.print_exc() - mod = _modules.get(template_id) + mod = _modules.get(template_id, False) - if mod and getattr(mod, "__template_enabled__", False) is not False: + if mod is None: + # Loaded but has no module, remove since there is no use in keeping it. + del _modules[template_id] + elif getattr(mod, "__template_enabled__", False) is not False: mod.__template_enabled__ = False try: @@ -124,7 +128,7 @@ def _disable(template_id, *, handle_error=None): handle_error(ex) else: print("\tapp_template_utils.disable: %s not %s." % - (template_id, "disabled" if mod is None else "loaded")) + (template_id, "disabled" if mod is False else "loaded")) if _bpy.app.debug_python: print("\tapp_template_utils.disable", template_id) @@ -170,10 +174,6 @@ def activate(template_id=None): if template_id_prev: _disable(template_id_prev) - # Disable all addons, afterwards caller must reset. - import addon_utils - addon_utils.disable_all() - # ignore_not_found so modules that don't contain scripts don't raise errors _mod = _enable(template_id, ignore_not_found=True) if template_id else None diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 2559a2f1df5..08e81d89c4f 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -2463,7 +2463,7 @@ def km_sequencer(params): {"properties": [("all", False)]}), ("sequencer.gap_remove", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True}, {"properties": [("all", True)]}), - ("sequencer.gap_insert", {"type": 'EQUAL', "value": 'PRESS', "shift": True}, None), + ("sequencer.gap_insert", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True}, None), ("sequencer.snap", {"type": 'S', "value": 'PRESS', "shift": True}, None), ("sequencer.swap_inputs", {"type": 'S', "value": 'PRESS', "alt": True}, None), *( @@ -2521,6 +2521,15 @@ def km_sequencer(params): {"properties": [("left_right", 'LEFT'), ("linked_time", True)]}), ("sequencer.select", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, {"properties": [("left_right", 'RIGHT'), ("linked_time", True)]}), + ("sequencer.select", {"type": 'EQUAL', "value": 'PRESS'}, + {"properties": [("left_right", 'OVERLAP'), ("linked_time", True)]}), + ("sequencer.select", {"type": 'LEFT_BRACKET', "value": 'PRESS', "shift": True}, + {"properties": [("left_right", 'LEFT'), ("linked_time", True), ("extend", True)]}), + ("sequencer.select", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True}, + {"properties": [("left_right", 'RIGHT'), ("linked_time", True), ("extend", True)]}), + ("sequencer.select", {"type": 'EQUAL', "value": 'PRESS', "shift": True}, + {"properties": [("left_right", 'OVERLAP'), ("linked_time", True), ("extend", True)]}), + *_template_items_context_menu("SEQUENCER_MT_context_menu", params.context_menu_event), ]) @@ -6263,6 +6272,16 @@ def km_3d_view_tool_sculpt_mesh_filter(params): ]}, ) +def km_3d_view_tool_sculpt_cloth_filter(params): + return ( + "3D View Tool: Sculpt, Cloth Filter", + {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, + {"items": [ + ("sculpt.cloth_filter", {"type": params.tool_tweak, "value": 'ANY'}, + None) + ]}, + ) + def km_3d_view_tool_paint_weight_sample_weight(params): return ( "3D View Tool: Paint Weight, Sample Weight", @@ -6802,6 +6821,7 @@ def generate_keymaps(params=None): km_3d_view_tool_sculpt_box_mask(params), km_3d_view_tool_sculpt_lasso_mask(params), km_3d_view_tool_sculpt_mesh_filter(params), + km_3d_view_tool_sculpt_cloth_filter(params), km_3d_view_tool_paint_weight_sample_weight(params), km_3d_view_tool_paint_weight_sample_vertex_group(params), km_3d_view_tool_paint_weight_gradient(params), diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py index 206f778195e..af071561232 100644 --- a/release/scripts/startup/bl_operators/sequencer.py +++ b/release/scripts/startup/bl_operators/sequencer.py @@ -188,7 +188,7 @@ class SequencerFadesAdd(Operator): ('CURSOR_TO', 'To Playhead', 'Fade from the start of sequences under the time cursor to the current frame'), ), name="Fade type", - description="Fade in, out, both in and out, to, or from the playhead. Default is both in and out", + description="Fade in, out, both in and out, to, or from the current frame. Default is both in and out", default='IN_OUT') @classmethod diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py index e859798c085..5f0fd3374d2 100644 --- a/release/scripts/startup/bl_ui/properties_output.py +++ b/release/scripts/startup/bl_ui/properties_output.py @@ -367,11 +367,11 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel): # I-frames layout.prop(ffmpeg, "gopsize") # B-Frames - split = layout.split(factor=0.5) - split.prop(ffmpeg, "use_max_b_frames", text="Max B-frames") - pbox = split.column() - pbox.prop(ffmpeg, "max_b_frames", text="") - pbox.enabled = ffmpeg.use_max_b_frames + row = layout.row(align=True, heading="Max B-frames") + row.prop(ffmpeg, "use_max_b_frames", text="") + sub = row.row(align=True) + sub.active = ffmpeg.use_max_b_frames + sub.prop(ffmpeg, "max_b_frames", text="") if not use_crf or ffmpeg.constant_rate_factor == 'NONE': col = layout.column() diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 5fadb31c83f..1612cce3c51 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -623,7 +623,7 @@ def brush_settings(layout, context, brush, popover=False): layout.prop(brush, "pose_origin_type") layout.prop(brush, "pose_offset") layout.prop(brush, "pose_smooth_iterations") - if brush.pose_deform_type == 'ROTATE_TWIST': + if brush.pose_deform_type == 'ROTATE_TWIST' and brush.pose_origin_type in ('TOPOLOGY','FACE_SETS'): layout.prop(brush, "pose_ik_segments") layout.prop(brush, "use_pose_ik_anchored") layout.separator() diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index 2c8ed363738..833cd05dd81 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -1174,7 +1174,7 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel): if domain.is_cache_baking_data and not domain.has_cache_baked_data: split.enabled = False - split.operator("fluid.pause_bake", text="Baking All - ESC to pause") + split.operator("fluid.pause_bake", text="Baking All - ESC to cancel") elif not domain.has_cache_baked_data and not domain.is_cache_baking_data: split.operator("fluid.bake_all", text="Bake All") else: diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 41c220f7ee4..4f317a97b38 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -244,6 +244,20 @@ class SEQUENCER_MT_preview_zoom(Menu): layout.operator_context = 'INVOKE_DEFAULT' +class SEQUENCER_MT_proxy(Menu): + bl_label = "Proxy" + + def draw(self, context): + layout = self.layout + + st = context.space_data + col = layout.column() + col.operator("sequencer.enable_proxies", text="Setup") + col.operator("sequencer.rebuild_proxy", text="Rebuild") + col.enabled = selected_sequences_len(context) >= 1 + layout.prop(st, "proxy_render_size", text="") + + class SEQUENCER_MT_view(Menu): bl_label = "View" @@ -291,6 +305,10 @@ class SEQUENCER_MT_view(Menu): layout.operator("view2d.zoom_border", text="Zoom") layout.menu("SEQUENCER_MT_preview_zoom") + layout.separator() + + layout.menu("SEQUENCER_MT_proxy") + layout.operator_context = 'INVOKE_DEFAULT' if is_sequencer_view: @@ -376,12 +394,15 @@ class SEQUENCER_MT_select_linked(Menu): layout.operator("sequencer.select_more", text="More") -class SEQUENCER_MT_select_playhead(Menu): - bl_label = "Select Playhead" +class SEQUENCER_MT_select_side_of_frame(Menu): + bl_label = "Side of Current Frame" def draw(self, _context): layout = self.layout + props = layout.operator("sequencer.select", text="Overlap") + props.left_right = 'OVERLAP' + props.linked_time = True props = layout.operator("sequencer.select", text="Left") props.left_right = 'LEFT' props.linked_time = True @@ -408,7 +429,7 @@ class SEQUENCER_MT_select(Menu): layout.separator() - layout.menu("SEQUENCER_MT_select_playhead", text="Playhead") + layout.menu("SEQUENCER_MT_select_side_of_frame") layout.menu("SEQUENCER_MT_select_handle", text="Handle") layout.menu("SEQUENCER_MT_select_channel", text="Channel") layout.menu("SEQUENCER_MT_select_linked", text="Linked") @@ -770,9 +791,6 @@ class SEQUENCER_MT_strip(Menu): layout.separator() layout.menu("SEQUENCER_MT_strip_input") - layout.separator() - layout.operator("sequencer.rebuild_proxy") - class SEQUENCER_MT_context_menu(Menu): bl_label = "Sequencer Context Menu" @@ -1042,7 +1060,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): strip_type = strip.type if strip_type == 'COLOR': - layout.prop(strip, "color") + layout.template_color_picker(strip, "color", value_slider=True, cubic=True) + layout.prop(strip, "color", text="") elif strip_type == 'WIPE': col = layout.column() @@ -1133,9 +1152,13 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): elif strip_type == 'TEXT': layout = self.layout - layout.use_property_split = False - layout.prop(strip, "text", text="") - layout.use_property_split = True + col = layout.column() + col.scale_x = 1.3 + col.scale_y = 1.3 + col.use_property_split = False + col.prop(strip, "text", text="") + col.use_property_split = True + layout.prop(strip, "wrap_width", text="Wrap Width") col = layout.column(align=True) if strip_type == 'SPEED': @@ -1172,9 +1195,8 @@ class SEQUENCER_PT_effect_text_layout(SequencerButtonsPanel, Panel): layout.use_property_split = True col = layout.column() col.prop(strip, "location", text="Location") - col.prop(strip, "align_x", text="Alignment X") + col.prop(strip, "align_x", text="Anchor X") col.prop(strip, "align_y", text="Y") - col.prop(strip, "wrap_width", text="Wrap Width") class SEQUENCER_PT_effect_text_style(SequencerButtonsPanel, Panel): @@ -1563,10 +1585,10 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): split.alignment = 'RIGHT' split.label(text="Playhead") split = split.split(factor=0.8 + max_factor, align=True) - playhead = frame_current - frame_final_start - split.label(text="{:>14}".format(smpte_from_frame(playhead))) + frame_display = frame_current - frame_final_start + split.label(text="{:>14}".format(smpte_from_frame(frame_display))) split.alignment = 'RIGHT' - split.label(text=str(playhead) + " ") + split.label(text=str(frame_display) + " ") if strip.type == 'SCENE': scene = strip.scene @@ -1664,7 +1686,7 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel): return strip.type in { 'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'MASK', - 'META', 'ADD', 'SUBTRACT', 'ALPHA_OVER', + 'META', 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'TEXT', 'ALPHA_UNDER', 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'MULTICAM', 'SPEED', 'ADJUSTMENT', 'COLORMIX' @@ -2198,7 +2220,8 @@ classes = ( SEQUENCER_MT_view_cache, SEQUENCER_MT_view_toggle, SEQUENCER_MT_preview_zoom, - SEQUENCER_MT_select_playhead, + SEQUENCER_MT_proxy, + SEQUENCER_MT_select_side_of_frame, SEQUENCER_MT_select_handle, SEQUENCER_MT_select_channel, SEQUENCER_MT_select_linked, diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 1aa5dde168b..b4c1ea5163f 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -1228,6 +1228,25 @@ class _defs_sculpt: draw_settings=draw_settings, ) + @ToolDef.from_fn + def cloth_filter(): + def draw_settings(_context, layout, tool): + props = tool.operator_properties("sculpt.cloth_filter") + layout.prop(props, "type", expand=False) + layout.prop(props, "strength") + layout.prop(props, "cloth_mass") + layout.prop(props, "cloth_damping") + layout.prop(props, "use_face_sets") + + return dict( + idname="builtin.cloth_filter", + label="Cloth Filter", + icon="ops.sculpt.cloth_filter", + widget=None, + keymap=(), + draw_settings=draw_settings, + ) + class _defs_vertex_paint: @@ -2402,6 +2421,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_sculpt.hide_border, None, _defs_sculpt.mesh_filter, + _defs_sculpt.cloth_filter, None, _defs_transform.translate, _defs_transform.rotate, diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 63fc44aed38..436d866886b 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1284,12 +1284,12 @@ class USERPREF_PT_saveload_autorun(FilePathsPanel, Panel): box = layout.box() row = box.row() row.label(text="Excluded Paths:") - row.operator("wm.userpref_autoexec_path_add", text="", icon='ADD', emboss=False) + row.operator("preferences.autoexec_path_add", text="", icon='ADD', emboss=False) for i, path_cmp in enumerate(prefs.autoexec_paths): row = box.row() row.prop(path_cmp, "path", text="") row.prop(path_cmp, "use_glob", text="", icon='FILTER') - row.operator("wm.userpref_autoexec_path_remove", text="", icon='X', emboss=False).index = i + row.operator("preferences.autoexec_path_remove", text="", icon='X', emboss=False).index = i # ----------------------------------------------------------------------------- diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 6dc21669f32..4795298d2f0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1224,6 +1224,7 @@ class VIEW3D_MT_view_cameras(Menu): layout.operator("view3d.object_as_camera") layout.operator("view3d.view_camera", text="Active Camera") + layout.operator("view3d.view_center_camera") class VIEW3D_MT_view_viewpoint(Menu): diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 458f1ab7a56..5d7e8fe743e 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -25,6 +25,7 @@ #include "BLI_bitmap.h" #include "BLI_kdopbvh.h" +#include "BLI_threads.h" #ifdef __cplusplus extern "C" { @@ -39,7 +40,7 @@ struct MFace; struct MVert; struct Mesh; -typedef struct LinkNode BVHCache; +struct BVHCache; /** * Struct that stores basic information about a BVHTree built from a edit-mesh. @@ -98,6 +99,9 @@ typedef enum BVHCacheType { BVHTREE_FROM_EM_VERTS, BVHTREE_FROM_EM_EDGES, BVHTREE_FROM_EM_LOOPTRI, + + /* Keep `BVHTREE_MAX_ITEM` as last item. */ + BVHTREE_MAX_ITEM, } BVHCacheType; /** @@ -122,7 +126,8 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -134,7 +139,8 @@ BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis); @@ -147,7 +153,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -161,7 +168,8 @@ BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -175,7 +183,8 @@ BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); BVHTree *bvhtree_from_editmesh_looptri( BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis); @@ -188,7 +197,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data, const struct MVert *vert, @@ -204,7 +214,8 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, struct Mesh *mesh, @@ -215,7 +226,8 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const int tree_type, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache); + struct BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex); /** * Frees data allocated by a call to bvhtree_from_mesh_*. @@ -244,10 +256,9 @@ float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray, /* Using local coordinates */ -bool bvhcache_find(const BVHCache *cache, BVHCacheType type, BVHTree **r_tree); -bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree); -void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, BVHCacheType type); -void bvhcache_free(BVHCache **cache_p); +bool bvhcache_has_tree(const struct BVHCache *bvh_cache, const BVHTree *tree); +struct BVHCache *bvhcache_init(void); +void bvhcache_free(struct BVHCache *bvh_cache); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index a314008f715..f4b56aa152f 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -50,6 +50,10 @@ typedef struct CollectionParent { struct Collection *BKE_collection_add(struct Main *bmain, struct Collection *parent, const char *name); +void BKE_collection_add_from_object(struct Main *bmain, + struct Scene *scene, + const struct Object *ob_src, + struct Collection *collection_dst); void BKE_collection_free(struct Collection *collection); bool BKE_collection_delete(struct Main *bmain, struct Collection *collection, bool hierarchy); diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 2084122929e..24db577322f 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -41,6 +41,7 @@ struct Object; struct Scene; struct SpaceImage; struct ToolSettings; +struct ViewLayer; struct bDeformGroup; struct bGPDframe; struct bGPDlayer; @@ -258,7 +259,8 @@ typedef void (*gpIterCb)(struct bGPDlayer *layer, struct bGPDstroke *stroke, void *thunk); -void BKE_gpencil_visible_stroke_iter(struct Object *ob, +void BKE_gpencil_visible_stroke_iter(struct ViewLayer *view_layer, + struct Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index ac292432acc..26ffd1bbfef 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -253,6 +253,7 @@ typedef struct SculptPoseIKChainSegment { typedef struct SculptPoseIKChain { SculptPoseIKChainSegment *segments; int tot_segments; + float grab_delta_offset[3]; } SculptPoseIKChain; /* Cloth Brush */ diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 2bf16e38716..8fb6f140822 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -82,8 +82,8 @@ typedef struct PBVHFrustumPlanes { int num_planes; } PBVHFrustumPlanes; -void BKE_pbvh_set_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes); -void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes); +void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes); +void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes); /* Callbacks */ @@ -98,7 +98,7 @@ typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float /* Building */ PBVH *BKE_pbvh_new(void); -void BKE_pbvh_build_mesh(PBVH *bvh, +void BKE_pbvh_build_mesh(PBVH *pbvh, const struct Mesh *mesh, const struct MPoly *mpoly, const struct MLoop *mloop, @@ -109,47 +109,47 @@ void BKE_pbvh_build_mesh(PBVH *bvh, struct CustomData *pdata, const struct MLoopTri *looptri, int looptri_num); -void BKE_pbvh_build_grids(PBVH *bvh, +void BKE_pbvh_build_grids(PBVH *pbvh, struct CCGElem **grid_elems, int totgrid, struct CCGKey *key, void **gridfaces, struct DMFlagMat *flagmats, unsigned int **grid_hidden); -void BKE_pbvh_build_bmesh(PBVH *bvh, +void BKE_pbvh_build_bmesh(PBVH *pbvh, struct BMesh *bm, bool smooth_shading, struct BMLog *log, const int cd_vert_node_offset, const int cd_face_node_offset); -void BKE_pbvh_free(PBVH *bvh); +void BKE_pbvh_free(PBVH *pbvh); /* Hierarchical Search in the BVH, two methods: * - for each hit calling a callback * - gather nodes in an array (easy to multithread) */ -void BKE_pbvh_search_callback(PBVH *bvh, +void BKE_pbvh_search_callback(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, BKE_pbvh_HitCallback hcb, void *hit_data); void BKE_pbvh_search_gather( - PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot); + PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot); /* Raycast * the hit callback is called for all leaf nodes intersecting the ray; * it's up to the callback to find the primitive within the leaves that is * hit first */ -void BKE_pbvh_raycast(PBVH *bvh, +void BKE_pbvh_raycast(PBVH *pbvh, BKE_pbvh_HitOccludedCallback cb, void *data, const float ray_start[3], const float ray_normal[3], bool original); -bool BKE_pbvh_node_raycast(PBVH *bvh, +bool BKE_pbvh_node_raycast(PBVH *pbvh, PBVHNode *node, float (*origco)[3], bool use_origco, @@ -170,16 +170,16 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node, /* for orthographic cameras, project the far away ray segment points to the root node so * we can have better precision. */ void BKE_pbvh_raycast_project_ray_root( - PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]); + PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]); -void BKE_pbvh_find_nearest_to_ray(PBVH *bvh, +void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh, BKE_pbvh_HitOccludedCallback cb, void *data, const float ray_start[3], const float ray_normal[3], bool original); -bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh, +bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh, PBVHNode *node, float (*origco)[3], bool use_origco, @@ -190,7 +190,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh, /* Drawing */ -void BKE_pbvh_draw_cb(PBVH *bvh, +void BKE_pbvh_draw_cb(PBVH *pbvh, bool update_only_visible, PBVHFrustumPlanes *update_frustum, PBVHFrustumPlanes *draw_frustum, @@ -198,7 +198,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh, void *user_data); void BKE_pbvh_draw_debug_cb( - PBVH *bvh, + PBVH *pbvh, void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag), void *user_data); @@ -209,26 +209,27 @@ typedef enum { PBVH_BMESH, } PBVHType; -PBVHType BKE_pbvh_type(const PBVH *bvh); -bool BKE_pbvh_has_faces(const PBVH *bvh); +PBVHType BKE_pbvh_type(const PBVH *pbvh); +bool BKE_pbvh_has_faces(const PBVH *pbvh); /* Get the PBVH root's bounding box */ -void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]); +void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]); /* multires hidden data, only valid for type == PBVH_GRIDS */ -unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh); +unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh); int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden, int *grid_indices, int totgrid, int gridsize); -void BKE_pbvh_sync_face_sets_to_grids(PBVH *bvh); +void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh); /* multires level, only valid for type == PBVH_GRIDS */ const struct CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh); struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh); +BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh); int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh); /* Only valid for type == PBVH_BMESH */ @@ -239,7 +240,7 @@ typedef enum { PBVH_Subdivide = 1, PBVH_Collapse = 2, } PBVHTopologyUpdateMode; -bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, +bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh, PBVHTopologyUpdateMode mode, const float center[3], const float view_normal[3], @@ -262,15 +263,15 @@ bool BKE_pbvh_node_fully_masked_get(PBVHNode *node); void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked); bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node); -void BKE_pbvh_node_get_grids(PBVH *bvh, +void BKE_pbvh_node_get_grids(PBVH *pbvh, PBVHNode *node, int **grid_indices, int *totgrid, int *maxgrid, int *gridsize, struct CCGElem ***grid_elems); -void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *r_totvert); -void BKE_pbvh_node_get_verts(PBVH *bvh, +void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert); +void BKE_pbvh_node_get_verts(PBVH *pbvh, PBVHNode *node, const int **r_vert_indices, struct MVert **r_verts); @@ -289,27 +290,27 @@ struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node); struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node); struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node); void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node); -void BKE_pbvh_bmesh_after_stroke(PBVH *bvh); +void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh); /* Update Bounding Box/Redraw and clear flags */ -void BKE_pbvh_update_bounds(PBVH *bvh, int flags); -void BKE_pbvh_update_vertex_data(PBVH *bvh, int flags); -void BKE_pbvh_update_visibility(PBVH *bvh); -void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg); -void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]); -void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface); -void BKE_pbvh_grids_update(PBVH *bvh, +void BKE_pbvh_update_bounds(PBVH *pbvh, int flags); +void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flags); +void BKE_pbvh_update_visibility(PBVH *pbvh); +void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg); +void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]); +void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface); +void BKE_pbvh_grids_update(PBVH *pbvh, struct CCGElem **grid_elems, void **gridfaces, struct DMFlagMat *flagmats, unsigned int **grid_hidden); -void BKE_pbvh_subdiv_cgg_set(PBVH *bvh, struct SubdivCCG *subdiv_ccg); -void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets); +void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, struct SubdivCCG *subdiv_ccg); +void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets); -void BKE_pbvh_face_sets_color_set(PBVH *bvh, int seed, int color_default); +void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default); -void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide); +void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide); /* vertex deformer */ float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3]; @@ -370,10 +371,10 @@ typedef struct PBVHVertexIter { bool visible; } PBVHVertexIter; -void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode); +void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode); -#define BKE_pbvh_vertex_iter_begin(bvh, node, vi, mode) \ - pbvh_vertex_iter_init(bvh, node, &vi, mode); \ +#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \ + pbvh_vertex_iter_init(pbvh, node, &vi, mode); \ \ for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \ if (vi.grids) { \ @@ -446,30 +447,30 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count); void BKE_pbvh_node_free_proxies(PBVHNode *node); -PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node); +PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node); void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode); void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node, int (**r_orco_tris)[3], int *r_orco_tris_num, float (**r_orco_coords)[3]); -bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node); +bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node); // void BKE_pbvh_node_BB_reset(PBVHNode *node); // void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]); -bool pbvh_has_mask(PBVH *bvh); -void pbvh_show_mask_set(PBVH *bvh, bool show_mask); +bool pbvh_has_mask(PBVH *pbvh); +void pbvh_show_mask_set(PBVH *pbvh, bool show_mask); -bool pbvh_has_face_sets(PBVH *bvh); -void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets); +bool pbvh_has_face_sets(PBVH *pbvh); +void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets); /* Parallelization */ void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode); -struct MVert *BKE_pbvh_get_verts(const PBVH *bvh); +struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 1fb4ca95c93..e8aa13a8beb 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -102,7 +102,7 @@ void BKE_blender_free(void) free_nodesystem(); } -static void blender_version_init() +static void blender_version_init(void) { const char *version_cycle = ""; if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) { @@ -130,7 +130,7 @@ static void blender_version_init() version_cycle); } -const char *BKE_blender_version_string() +const char *BKE_blender_version_string(void) { return blender_version_string; } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 133917e441c..3241518cae5 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -520,6 +520,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) Material *ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2); if (ma == NULL) { ma = BKE_gpencil_material_add(bmain, "Dots Stroke"); + ma->gp_style->mode = GP_MATERIAL_MODE_DOT; } brush->gpencil_settings->material = ma; /* Pin the matterial to the brush. */ @@ -744,6 +745,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) Material *ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2); if (ma == NULL) { ma = BKE_gpencil_material_add(bmain, "Dots Stroke"); + ma->gp_style->mode = GP_MATERIAL_MODE_DOT; } brush->gpencil_settings->material = ma; /* Pin the matterial to the brush. */ diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index cd90ebc2eed..93794eb9709 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -41,8 +41,126 @@ #include "MEM_guardedalloc.h" -static ThreadRWMutex cache_rwlock = BLI_RWLOCK_INITIALIZER; +/* -------------------------------------------------------------------- */ +/** \name BVHCache + * \{ */ + +typedef struct BVHCacheItem { + bool is_filled; + BVHTree *tree; +} BVHCacheItem; + +typedef struct BVHCache { + BVHCacheItem items[BVHTREE_MAX_ITEM]; + ThreadMutex mutex; +} BVHCache; + +/** + * Queries a bvhcache for the cache bvhtree of the request type + * + * When the `r_locked` is filled and the tree could not be found the caches mutex will be + * locked. This mutex can be unlocked by calling `bvhcache_unlock`. + * + * When `r_locked` is used the `mesh_eval_mutex` must contain the `Mesh_Runtime.eval_mutex`. + */ +static bool bvhcache_find(BVHCache **bvh_cache_p, + BVHCacheType type, + BVHTree **r_tree, + bool *r_locked, + ThreadMutex *mesh_eval_mutex) +{ + bool do_lock = r_locked; + if (r_locked) { + *r_locked = false; + } + if (*bvh_cache_p == NULL) { + if (!do_lock) { + /* Cache does not exist and no lock is requested. */ + return false; + } + /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */ + BLI_mutex_lock(mesh_eval_mutex); + if (*bvh_cache_p == NULL) { + *bvh_cache_p = bvhcache_init(); + } + BLI_mutex_unlock(mesh_eval_mutex); + } + BVHCache *bvh_cache = *bvh_cache_p; + if (bvh_cache->items[type].is_filled) { + *r_tree = bvh_cache->items[type].tree; + return true; + } + if (do_lock) { + BLI_mutex_lock(&bvh_cache->mutex); + bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, NULL, NULL); + if (in_cache) { + BLI_mutex_unlock(&bvh_cache->mutex); + return in_cache; + } + *r_locked = true; + } + return false; +} + +static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started) +{ + if (lock_started) { + BLI_mutex_unlock(&bvh_cache->mutex); + } +} + +bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree) +{ + if (bvh_cache == NULL) { + return false; + } + + for (BVHCacheType i = 0; i < BVHTREE_MAX_ITEM; i++) { + if (bvh_cache->items[i].tree == tree) { + return true; + } + } + return false; +} + +BVHCache *bvhcache_init(void) +{ + BVHCache *cache = MEM_callocN(sizeof(BVHCache), __func__); + BLI_mutex_init(&cache->mutex); + return cache; +} +/** + * Inserts a BVHTree of the given type under the cache + * After that the caller no longer needs to worry when to free the BVHTree + * as that will be done when the cache is freed. + * + * A call to this assumes that there was no previous cached tree of the given type + * \warning The #BVHTree can be NULL. + */ +static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type) +{ + BVHCacheItem *item = &bvh_cache->items[type]; + BLI_assert(!item->is_filled); + item->tree = tree; + item->is_filled = true; +} + +/** + * frees a bvhcache + */ +void bvhcache_free(BVHCache *bvh_cache) +{ + for (BVHCacheType index = 0; index < BVHTREE_MAX_ITEM; index++) { + BVHCacheItem *item = &bvh_cache->items[index]; + BLI_bvhtree_free(item->tree); + item->tree = NULL; + } + BLI_mutex_end(&bvh_cache->mutex); + MEM_freeN(bvh_cache); +} + +/** \} */ /* -------------------------------------------------------------------- */ /** \name Local Callbacks * \{ */ @@ -518,29 +636,26 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { BVHTree *tree = NULL; - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); - BLI_rw_mutex_unlock(&cache_rwlock); + if (bvh_cache_p) { + bool lock_started = false; + data->cached = bvhcache_find( + bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex); if (data->cached == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); - if (data->cached == false) { - tree = bvhtree_from_editmesh_verts_create_tree( - epsilon, tree_type, axis, em, verts_mask, verts_num_active); - - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(bvh_cache, tree, bvh_cache_type); - data->cached = true; - } - BLI_rw_mutex_unlock(&cache_rwlock); + tree = bvhtree_from_editmesh_verts_create_tree( + epsilon, tree_type, axis, em, verts_mask, verts_num_active); + + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(*bvh_cache_p, tree, bvh_cache_type); + data->cached = true; } + bvhcache_unlock(*bvh_cache_p, lock_started); } else { tree = bvhtree_from_editmesh_verts_create_tree( @@ -553,7 +668,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, data->em = em; data->nearest_callback = NULL; data->raycast_callback = editmesh_verts_spherecast; - data->cached = bvh_cache != NULL; + data->cached = bvh_cache_p != NULL; } return tree; @@ -562,7 +677,8 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data, BVHTree *bvhtree_from_editmesh_verts( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { - return bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL); + return bvhtree_from_editmesh_verts_ex( + data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); } /** @@ -582,32 +698,26 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { bool in_cache = false; + bool lock_started = false; BVHTree *tree = NULL; - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - BLI_rw_mutex_unlock(&cache_rwlock); - if (in_cache == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - if (in_cache) { - BLI_rw_mutex_unlock(&cache_rwlock); - } - } + if (bvh_cache_p) { + in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } if (in_cache == false) { tree = bvhtree_from_mesh_verts_create_tree( epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active); - if (bvh_cache) { + if (bvh_cache_p) { /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ + BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); - BLI_rw_mutex_unlock(&cache_rwlock); + bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } @@ -735,29 +845,26 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { BVHTree *tree = NULL; - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); - BLI_rw_mutex_unlock(&cache_rwlock); - + if (bvh_cache_p) { + bool lock_started = false; + data->cached = bvhcache_find( + bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex); + BVHCache *bvh_cache = *bvh_cache_p; if (data->cached == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree); - if (data->cached == false) { - tree = bvhtree_from_editmesh_edges_create_tree( - epsilon, tree_type, axis, em, edges_mask, edges_num_active); - - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(bvh_cache, tree, bvh_cache_type); - data->cached = true; - } - BLI_rw_mutex_unlock(&cache_rwlock); + tree = bvhtree_from_editmesh_edges_create_tree( + epsilon, tree_type, axis, em, edges_mask, edges_num_active); + + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(bvh_cache, tree, bvh_cache_type); + data->cached = true; } + bvhcache_unlock(bvh_cache, lock_started); } else { tree = bvhtree_from_editmesh_edges_create_tree( @@ -770,7 +877,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, data->em = em; data->nearest_callback = NULL; /* TODO */ data->raycast_callback = NULL; /* TODO */ - data->cached = bvh_cache != NULL; + data->cached = bvh_cache_p != NULL; } return tree; @@ -779,7 +886,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data, BVHTree *bvhtree_from_editmesh_edges( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { - return bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL); + return bvhtree_from_editmesh_edges_ex( + data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); } /** @@ -802,32 +910,26 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { bool in_cache = false; + bool lock_started = false; BVHTree *tree = NULL; - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - BLI_rw_mutex_unlock(&cache_rwlock); - if (in_cache == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - if (in_cache) { - BLI_rw_mutex_unlock(&cache_rwlock); - } - } + if (bvh_cache_p) { + in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } if (in_cache == false) { tree = bvhtree_from_mesh_edges_create_tree( vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis); - if (bvh_cache) { + if (bvh_cache_p) { + BVHCache *bvh_cache = *bvh_cache_p; /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ bvhcache_insert(bvh_cache, tree, bvh_cache_type); - BLI_rw_mutex_unlock(&cache_rwlock); + bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } @@ -937,32 +1039,26 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { bool in_cache = false; + bool lock_started = false; BVHTree *tree = NULL; - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - BLI_rw_mutex_unlock(&cache_rwlock); - if (in_cache == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - if (in_cache) { - BLI_rw_mutex_unlock(&cache_rwlock); - } - } + if (bvh_cache_p) { + in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } if (in_cache == false) { tree = bvhtree_from_mesh_faces_create_tree( epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active); - if (bvh_cache) { + if (bvh_cache_p) { /* Save on cache for later use */ /* printf("BVHTree built and saved on cache\n"); */ + BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); - BLI_rw_mutex_unlock(&cache_rwlock); + bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } @@ -1113,29 +1209,28 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { /* BMESH specific check that we have tessfaces, * we _could_ tessellate here but rather not - campbell */ BVHTree *tree = NULL; - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - bool in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - BLI_rw_mutex_unlock(&cache_rwlock); + if (bvh_cache_p) { + bool lock_started = false; + bool in_cache = bvhcache_find( + bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); + BVHCache *bvh_cache = *bvh_cache_p; + if (in_cache == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - if (in_cache == false) { - tree = bvhtree_from_editmesh_looptri_create_tree( - epsilon, tree_type, axis, em, looptri_mask, looptri_num_active); - - /* Save on cache for later use */ - /* printf("BVHTree built and saved on cache\n"); */ - bvhcache_insert(bvh_cache, tree, bvh_cache_type); - } - BLI_rw_mutex_unlock(&cache_rwlock); + tree = bvhtree_from_editmesh_looptri_create_tree( + epsilon, tree_type, axis, em, looptri_mask, looptri_num_active); + + /* Save on cache for later use */ + /* printf("BVHTree built and saved on cache\n"); */ + bvhcache_insert(bvh_cache, tree, bvh_cache_type); } + bvhcache_unlock(bvh_cache, lock_started); } else { tree = bvhtree_from_editmesh_looptri_create_tree( @@ -1147,7 +1242,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, data->nearest_callback = editmesh_looptri_nearest_point; data->raycast_callback = editmesh_looptri_spherecast; data->em = em; - data->cached = bvh_cache != NULL; + data->cached = bvh_cache_p != NULL; } return tree; } @@ -1155,7 +1250,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data, BVHTree *bvhtree_from_editmesh_looptri( BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis) { - return bvhtree_from_editmesh_looptri_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL); + return bvhtree_from_editmesh_looptri_ex( + data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL); } /** @@ -1177,21 +1273,14 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, int tree_type, int axis, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { bool in_cache = false; + bool lock_started = false; BVHTree *tree = NULL; - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - BLI_rw_mutex_unlock(&cache_rwlock); - if (in_cache == false) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE); - in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - if (in_cache) { - BLI_rw_mutex_unlock(&cache_rwlock); - } - } + if (bvh_cache_p) { + in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex); } if (in_cache == false) { @@ -1206,9 +1295,10 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data, looptri_mask, looptri_num_active); - if (bvh_cache) { + if (bvh_cache_p) { + BVHCache *bvh_cache = *bvh_cache_p; bvhcache_insert(bvh_cache, tree, bvh_cache_type); - BLI_rw_mutex_unlock(&cache_rwlock); + bvhcache_unlock(bvh_cache, lock_started); in_cache = true; } } @@ -1315,11 +1405,10 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const int tree_type) { BVHTree *tree = NULL; - BVHCache **bvh_cache = &mesh->runtime.bvh_cache; + BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache; + ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex; - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - bool is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - BLI_rw_mutex_unlock(&cache_rwlock); + bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL); if (is_cached && tree == NULL) { memset(data, 0, sizeof(*data)); @@ -1351,7 +1440,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, tree_type, 6, bvh_cache_type, - bvh_cache); + bvh_cache_p, + mesh_eval_mutex); if (loose_verts_mask != NULL) { MEM_freeN(loose_verts_mask); @@ -1386,7 +1476,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, tree_type, 6, bvh_cache_type, - bvh_cache); + bvh_cache_p, + mesh_eval_mutex); if (loose_edges_mask != NULL) { MEM_freeN(loose_edges_mask); @@ -1416,7 +1507,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, tree_type, 6, bvh_cache_type, - bvh_cache); + bvh_cache_p, + mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ @@ -1452,7 +1544,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, tree_type, 6, bvh_cache_type, - bvh_cache); + bvh_cache_p, + mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ @@ -1464,6 +1557,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, case BVHTREE_FROM_EM_VERTS: case BVHTREE_FROM_EM_EDGES: case BVHTREE_FROM_EM_LOOPTRI: + case BVHTREE_MAX_ITEM: BLI_assert(false); break; } @@ -1493,17 +1587,16 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, struct BMEditMesh *em, const int tree_type, const BVHCacheType bvh_cache_type, - BVHCache **bvh_cache) + BVHCache **bvh_cache_p, + ThreadMutex *mesh_eval_mutex) { BVHTree *tree = NULL; bool is_cached = false; memset(data, 0, sizeof(*data)); - if (bvh_cache) { - BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ); - is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree); - BLI_rw_mutex_unlock(&cache_rwlock); + if (bvh_cache_p) { + is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL); if (is_cached && tree == NULL) { return tree; @@ -1517,7 +1610,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, case BVHTREE_FROM_EM_VERTS: if (is_cached == false) { tree = bvhtree_from_editmesh_verts_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache); + data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); } else { data->nearest_callback = NULL; @@ -1528,7 +1621,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, case BVHTREE_FROM_EM_EDGES: if (is_cached == false) { tree = bvhtree_from_editmesh_edges_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache); + data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ @@ -1540,7 +1633,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, case BVHTREE_FROM_EM_LOOPTRI: if (is_cached == false) { tree = bvhtree_from_editmesh_looptri_ex( - data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache); + data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex); } else { /* Setup BVHTreeFromMesh */ @@ -1555,6 +1648,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data, case BVHTREE_FROM_LOOPTRI_NO_HIDDEN: case BVHTREE_FROM_LOOSEVERTS: case BVHTREE_FROM_LOOSEEDGES: + case BVHTREE_MAX_ITEM: BLI_assert(false); break; } @@ -1615,82 +1709,3 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) memset(data, 0, sizeof(*data)); } - -/* -------------------------------------------------------------------- */ -/** \name BVHCache - * \{ */ - -typedef struct BVHCacheItem { - BVHCacheType type; - BVHTree *tree; - -} BVHCacheItem; - -/** - * Queries a bvhcache for the cache bvhtree of the request type - */ -bool bvhcache_find(const BVHCache *cache, BVHCacheType type, BVHTree **r_tree) -{ - while (cache) { - const BVHCacheItem *item = cache->link; - if (item->type == type) { - *r_tree = item->tree; - return true; - } - cache = cache->next; - } - return false; -} - -bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree) -{ - while (cache) { - const BVHCacheItem *item = cache->link; - if (item->tree == tree) { - return true; - } - cache = cache->next; - } - return false; -} - -/** - * Inserts a BVHTree of the given type under the cache - * After that the caller no longer needs to worry when to free the BVHTree - * as that will be done when the cache is freed. - * - * A call to this assumes that there was no previous cached tree of the given type - * \warning The #BVHTree can be NULL. - */ -void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, BVHCacheType type) -{ - BVHCacheItem *item = NULL; - - BLI_assert(bvhcache_find(*cache_p, type, &(BVHTree *){0}) == false); - - item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem"); - - item->type = type; - item->tree = tree; - - BLI_linklist_prepend(cache_p, item); -} - -/** - * frees a bvhcache - */ -static void bvhcacheitem_free(void *_item) -{ - BVHCacheItem *item = (BVHCacheItem *)_item; - - BLI_bvhtree_free(item->tree); - MEM_freeN(item); -} - -void bvhcache_free(BVHCache **cache_p) -{ - BLI_linklist_free(*cache_p, (LinkNodeFreeFP)bvhcacheitem_free); - *cache_p = NULL; -} - -/** \} */ diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index a28cc73cb94..1352c0b8a14 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -210,6 +210,34 @@ Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const return collection; } +/** + * Add \a collection_dst to all scene collections that reference object \a ob_src is in. + * Used to replace an instance object with a collection (library override operator). + * + * Logic is very similar to #BKE_collection_object_add_from(). + */ +void BKE_collection_add_from_object(Main *bmain, + Scene *scene, + const Object *ob_src, + Collection *collection_dst) +{ + bool is_instantiated = false; + + FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { + if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) { + collection_child_add(collection, collection_dst, 0, true); + is_instantiated = true; + } + } + FOREACH_SCENE_COLLECTION_END; + + if (!is_instantiated) { + collection_child_add(scene->master_collection, collection_dst, 0, true); + } + + BKE_main_collection_sync(bmain); +} + /*********************** Free and Delete Collection ****************************/ /** Free (or release) any data used by this collection (does not free the collection itself). */ @@ -761,8 +789,10 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob) } /** - * Add object to all scene collections that reference object is in - * (used to copy objects). + * Add \a ob_dst to all scene collections that reference object \a ob_src is in. + * Used for copying objects. + * + * Logic is very similar to #BKE_collection_add_from_object() */ void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst) { diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index 7f65dfc2b51..5ba3bfa0ff7 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -1895,8 +1895,13 @@ bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size, * * \{ */ -void BKE_gpencil_visible_stroke_iter( - Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, bool do_onion, int cfra) +void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, + Object *ob, + gpIterCb layer_cb, + gpIterCb stroke_cb, + void *thunk, + bool do_onion, + int cfra) { bGPdata *gpd = (bGPdata *)ob->data; const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); @@ -1918,6 +1923,14 @@ void BKE_gpencil_visible_stroke_iter( continue; } + /* Hide the layer if it's defined a view layer filter. This is used to + * generate renders, putting only selected GP layers for each View Layer. + * This is used only in final render and never in Viewport. */ + if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') && + (!STREQ(view_layer->name, gpl->viewlayername))) { + continue; + } + if (is_multiedit) { sta_gpf = end_gpf = NULL; /* Check the whole range and tag the editable frames. */ diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 795390f1940..9426d229e01 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -46,6 +46,11 @@ #include "RNA_types.h" #define OVERRIDE_AUTO_CHECK_DELAY 0.2 /* 200ms between auto-override checks. */ +//#define DEBUG_OVERRIDE_TIMEIT + +#ifdef DEBUG_OVERRIDE_TIMEIT +# include "PIL_time_utildefines.h" +#endif static void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst, IDOverrideLibraryProperty *op_src); @@ -1027,7 +1032,7 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain, ID *storage_id; #ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_START_AVERAGED(BKE_override_operations_store_start); + TIMEIT_START_AVERAGED(BKE_lib_override_library_operations_store_start); #endif /* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy @@ -1055,12 +1060,13 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain, local->override_library->storage = storage_id; #ifdef DEBUG_OVERRIDE_TIMEIT - TIMEIT_END_AVERAGED(BKE_override_operations_store_start); + TIMEIT_END_AVERAGED(BKE_lib_override_library_operations_store_start); #endif return storage_id; } -/** Restore given ID modified by \a BKE_override_operations_store_start, to its original state. */ +/** Restore given ID modified by \a BKE_lib_override_library_operations_store_start, to its + * original state. */ void BKE_lib_override_library_operations_store_end( OverrideLibraryStorage *UNUSED(override_storage), ID *local) { diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c index d09205b5744..404d6a581ae 100644 --- a/source/blender/blenkernel/intern/mesh_remap.c +++ b/source/blender/blenkernel/intern/mesh_remap.c @@ -1555,6 +1555,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, 2, 6, 0, + NULL, NULL); } @@ -1598,6 +1599,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode, 2, 6, 0, + NULL, NULL); } diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c index aa3586d1e3d..8bce577897b 100644 --- a/source/blender/blenkernel/intern/mesh_runtime.c +++ b/source/blender/blenkernel/intern/mesh_runtime.c @@ -53,6 +53,7 @@ void BKE_mesh_runtime_reset(Mesh *mesh) memset(&mesh->runtime, 0, sizeof(mesh->runtime)); mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex"); BLI_mutex_init(mesh->runtime.eval_mutex); + mesh->runtime.bvh_cache = NULL; } /* Clear all pointers which we don't want to be shared on copying the datablock. @@ -227,7 +228,10 @@ bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh) void BKE_mesh_runtime_clear_geometry(Mesh *mesh) { - bvhcache_free(&mesh->runtime.bvh_cache); + if (mesh->runtime.bvh_cache) { + bvhcache_free(mesh->runtime.bvh_cache); + mesh->runtime.bvh_cache = NULL; + } MEM_SAFE_FREE(mesh->runtime.looptris.array); /* TODO(sergey): Does this really belong here? */ if (mesh->runtime.subdiv_ccg != NULL) { diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index e31d2a8e005..19f28047b80 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -61,7 +61,7 @@ typedef struct PBVHStack { } PBVHStack; typedef struct PBVHIter { - PBVH *bvh; + PBVH *pbvh; BKE_pbvh_SearchCallback scb; void *search_data; @@ -131,7 +131,7 @@ void BBC_update_centroid(BBC *bbc) } /* Not recursive */ -static void update_node_vb(PBVH *bvh, PBVHNode *node) +static void update_node_vb(PBVH *pbvh, PBVHNode *node) { BB vb; @@ -140,15 +140,15 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node) if (node->flag & PBVH_Leaf) { PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL) + BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL) { BB_expand(&vb, vd.co); } BKE_pbvh_vertex_iter_end; } else { - BB_expand_with_bb(&vb, &bvh->nodes[node->children_offset].vb); - BB_expand_with_bb(&vb, &bvh->nodes[node->children_offset + 1].vb); + BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset].vb); + BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset + 1].vb); } node->vb = vb; @@ -197,24 +197,24 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis, float } /* Returns the index of the first element on the right of the partition */ -static int partition_indices_material(PBVH *bvh, int lo, int hi) +static int partition_indices_material(PBVH *pbvh, int lo, int hi) { - const MPoly *mpoly = bvh->mpoly; - const MLoopTri *looptri = bvh->looptri; - const DMFlagMat *flagmats = bvh->grid_flag_mats; - const int *indices = bvh->prim_indices; + const MPoly *mpoly = pbvh->mpoly; + const MLoopTri *looptri = pbvh->looptri; + const DMFlagMat *flagmats = pbvh->grid_flag_mats; + const int *indices = pbvh->prim_indices; const void *first; int i = lo, j = hi; - if (bvh->looptri) { - first = &mpoly[looptri[bvh->prim_indices[lo]].poly]; + if (pbvh->looptri) { + first = &mpoly[looptri[pbvh->prim_indices[lo]].poly]; } else { - first = &flagmats[bvh->prim_indices[lo]]; + first = &flagmats[pbvh->prim_indices[lo]]; } for (;;) { - if (bvh->looptri) { + if (pbvh->looptri) { for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) { /* pass */ } @@ -235,36 +235,36 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi) return i; } - SWAP(int, bvh->prim_indices[i], bvh->prim_indices[j]); + SWAP(int, pbvh->prim_indices[i], pbvh->prim_indices[j]); i++; } } -void pbvh_grow_nodes(PBVH *bvh, int totnode) +void pbvh_grow_nodes(PBVH *pbvh, int totnode) { - if (UNLIKELY(totnode > bvh->node_mem_count)) { - bvh->node_mem_count = bvh->node_mem_count + (bvh->node_mem_count / 3); - if (bvh->node_mem_count < totnode) { - bvh->node_mem_count = totnode; + if (UNLIKELY(totnode > pbvh->node_mem_count)) { + pbvh->node_mem_count = pbvh->node_mem_count + (pbvh->node_mem_count / 3); + if (pbvh->node_mem_count < totnode) { + pbvh->node_mem_count = totnode; } - bvh->nodes = MEM_recallocN(bvh->nodes, sizeof(PBVHNode) * bvh->node_mem_count); + pbvh->nodes = MEM_recallocN(pbvh->nodes, sizeof(PBVHNode) * pbvh->node_mem_count); } - bvh->totnode = totnode; + pbvh->totnode = totnode; } /* Add a vertex to the map, with a positive value for unique vertices and * a negative value for additional vertices */ static int map_insert_vert( - PBVH *bvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex) + PBVH *pbvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex) { void *key, **value_p; key = POINTER_FROM_INT(vertex); if (!BLI_ghash_ensure_p(map, key, &value_p)) { int value_i; - if (BLI_BITMAP_TEST(bvh->vert_bitmap, vertex) == 0) { - BLI_BITMAP_ENABLE(bvh->vert_bitmap, vertex); + if (BLI_BITMAP_TEST(pbvh->vert_bitmap, vertex) == 0) { + BLI_BITMAP_ENABLE(pbvh->vert_bitmap, vertex); value_i = *uniq_verts; (*uniq_verts)++; } @@ -281,7 +281,7 @@ static int map_insert_vert( } /* Find vertices used by the faces in this node and update the draw buffers */ -static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) +static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node) { bool has_visible = false; @@ -295,19 +295,19 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) node->face_vert_indices = (const int(*)[3])face_vert_indices; - if (bvh->respect_hide == false) { + if (pbvh->respect_hide == false) { has_visible = true; } for (int i = 0; i < totface; i++) { - const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]]; + const MLoopTri *lt = &pbvh->looptri[node->prim_indices[i]]; for (int j = 0; j < 3; j++) { face_vert_indices[i][j] = map_insert_vert( - bvh, map, &node->face_verts, &node->uniq_verts, bvh->mloop[lt->tri[j]].v); + pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->mloop[lt->tri[j]].v); } if (has_visible == false) { - if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) { + if (!paint_is_face_hidden(lt, pbvh->verts, pbvh->mloop)) { has_visible = true; } } @@ -347,11 +347,11 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) BLI_ghash_free(map, NULL, NULL); } -static void update_vb(PBVH *bvh, PBVHNode *node, BBC *prim_bbc, int offset, int count) +static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int count) { BB_reset(&node->vb); for (int i = offset + count - 1; i >= offset; i--) { - BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[bvh->prim_indices[i]])); + BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[pbvh->prim_indices[i]])); } node->orig_vb = node->vb; } @@ -389,77 +389,78 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden, return totquad; } -void BKE_pbvh_sync_face_sets_to_grids(PBVH *bvh) +void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh) { - const int gridsize = bvh->gridkey.grid_size; - for (int i = 0; i < bvh->totgrid; i++) { - BLI_bitmap *gh = bvh->grid_hidden[i]; - const int face_index = BKE_subdiv_ccg_grid_to_face_index(bvh->subdiv_ccg, i); - if (!gh && bvh->face_sets[face_index] < 0) { - gh = bvh->grid_hidden[i] = BLI_BITMAP_NEW(bvh->gridkey.grid_area, "partialvis_update_grids"); + const int gridsize = pbvh->gridkey.grid_size; + for (int i = 0; i < pbvh->totgrid; i++) { + BLI_bitmap *gh = pbvh->grid_hidden[i]; + const int face_index = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, i); + if (!gh && pbvh->face_sets[face_index] < 0) { + gh = pbvh->grid_hidden[i] = BLI_BITMAP_NEW(pbvh->gridkey.grid_area, + "partialvis_update_grids"); } if (gh) { for (int y = 0; y < gridsize; y++) { for (int x = 0; x < gridsize; x++) { - BLI_BITMAP_SET(gh, y * gridsize + x, bvh->face_sets[face_index] < 0); + BLI_BITMAP_SET(gh, y * gridsize + x, pbvh->face_sets[face_index] < 0); } } } } } -static void build_grid_leaf_node(PBVH *bvh, PBVHNode *node) +static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node) { int totquads = BKE_pbvh_count_grid_quads( - bvh->grid_hidden, node->prim_indices, node->totprim, bvh->gridkey.grid_size); + pbvh->grid_hidden, node->prim_indices, node->totprim, pbvh->gridkey.grid_size); BKE_pbvh_node_fully_hidden_set(node, (totquads == 0)); BKE_pbvh_node_mark_rebuild_draw(node); } -static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc, int offset, int count) +static void build_leaf(PBVH *pbvh, int node_index, BBC *prim_bbc, int offset, int count) { - bvh->nodes[node_index].flag |= PBVH_Leaf; + pbvh->nodes[node_index].flag |= PBVH_Leaf; - bvh->nodes[node_index].prim_indices = bvh->prim_indices + offset; - bvh->nodes[node_index].totprim = count; + pbvh->nodes[node_index].prim_indices = pbvh->prim_indices + offset; + pbvh->nodes[node_index].totprim = count; /* Still need vb for searches */ - update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count); + update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count); - if (bvh->looptri) { - build_mesh_leaf_node(bvh, bvh->nodes + node_index); + if (pbvh->looptri) { + build_mesh_leaf_node(pbvh, pbvh->nodes + node_index); } else { - build_grid_leaf_node(bvh, bvh->nodes + node_index); + build_grid_leaf_node(pbvh, pbvh->nodes + node_index); } } /* Return zero if all primitives in the node can be drawn with the * same material (including flat/smooth shading), non-zero otherwise */ -static bool leaf_needs_material_split(PBVH *bvh, int offset, int count) +static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count) { if (count <= 1) { return false; } - if (bvh->looptri) { - const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]]; - const MPoly *mp = &bvh->mpoly[first->poly]; + if (pbvh->looptri) { + const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]]; + const MPoly *mp = &pbvh->mpoly[first->poly]; for (int i = offset + count - 1; i > offset; i--) { - int prim = bvh->prim_indices[i]; - const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly]; + int prim = pbvh->prim_indices[i]; + const MPoly *mp_other = &pbvh->mpoly[pbvh->looptri[prim].poly]; if (!face_materials_match(mp, mp_other)) { return true; } } } else { - const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]]; + const DMFlagMat *first = &pbvh->grid_flag_mats[pbvh->prim_indices[offset]]; for (int i = offset + count - 1; i > offset; i--) { - int prim = bvh->prim_indices[i]; - if (!grid_materials_match(first, &bvh->grid_flag_mats[prim])) { + int prim = pbvh->prim_indices[i]; + if (!grid_materials_match(first, &pbvh->grid_flag_mats[prim])) { return true; } } @@ -479,26 +480,26 @@ static bool leaf_needs_material_split(PBVH *bvh, int offset, int count) * offset and start indicate a range in the array of primitive indices */ -static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offset, int count) +static void build_sub(PBVH *pbvh, int node_index, BB *cb, BBC *prim_bbc, int offset, int count) { int end; BB cb_backing; /* Decide whether this is a leaf or not */ - const bool below_leaf_limit = count <= bvh->leaf_limit; + const bool below_leaf_limit = count <= pbvh->leaf_limit; if (below_leaf_limit) { - if (!leaf_needs_material_split(bvh, offset, count)) { - build_leaf(bvh, node_index, prim_bbc, offset, count); + if (!leaf_needs_material_split(pbvh, offset, count)) { + build_leaf(pbvh, node_index, prim_bbc, offset, count); return; } } /* Add two child nodes */ - bvh->nodes[node_index].children_offset = bvh->totnode; - pbvh_grow_nodes(bvh, bvh->totnode + 2); + pbvh->nodes[node_index].children_offset = pbvh->totnode; + pbvh_grow_nodes(pbvh, pbvh->totnode + 2); /* Update parent node bounding box */ - update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count); + update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count); if (!below_leaf_limit) { /* Find axis with widest range of primitive centroids */ @@ -506,13 +507,13 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offs cb = &cb_backing; BB_reset(cb); for (int i = offset + count - 1; i >= offset; i--) { - BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid); + BB_expand(cb, prim_bbc[pbvh->prim_indices[i]].bcentroid); } } const int axis = BB_widest_axis(cb); /* Partition primitives along that axis */ - end = partition_indices(bvh->prim_indices, + end = partition_indices(pbvh->prim_indices, offset, offset + count - 1, axis, @@ -521,38 +522,42 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offs } else { /* Partition primitives by material */ - end = partition_indices_material(bvh, offset, offset + count - 1); + end = partition_indices_material(pbvh, offset, offset + count - 1); } /* Build children */ - build_sub(bvh, bvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset); - build_sub( - bvh, bvh->nodes[node_index].children_offset + 1, NULL, prim_bbc, end, offset + count - end); + build_sub(pbvh, pbvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset); + build_sub(pbvh, + pbvh->nodes[node_index].children_offset + 1, + NULL, + prim_bbc, + end, + offset + count - end); } -static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim) +static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim) { - if (totprim != bvh->totprim) { - bvh->totprim = totprim; - if (bvh->nodes) { - MEM_freeN(bvh->nodes); + if (totprim != pbvh->totprim) { + pbvh->totprim = totprim; + if (pbvh->nodes) { + MEM_freeN(pbvh->nodes); } - if (bvh->prim_indices) { - MEM_freeN(bvh->prim_indices); + if (pbvh->prim_indices) { + MEM_freeN(pbvh->prim_indices); } - bvh->prim_indices = MEM_mallocN(sizeof(int) * totprim, "bvh prim indices"); + pbvh->prim_indices = MEM_mallocN(sizeof(int) * totprim, "bvh prim indices"); for (int i = 0; i < totprim; i++) { - bvh->prim_indices[i] = i; + pbvh->prim_indices[i] = i; } - bvh->totnode = 0; - if (bvh->node_mem_count < 100) { - bvh->node_mem_count = 100; - bvh->nodes = MEM_callocN(sizeof(PBVHNode) * bvh->node_mem_count, "bvh initial nodes"); + pbvh->totnode = 0; + if (pbvh->node_mem_count < 100) { + pbvh->node_mem_count = 100; + pbvh->nodes = MEM_callocN(sizeof(PBVHNode) * pbvh->node_mem_count, "bvh initial nodes"); } } - bvh->totnode = 1; - build_sub(bvh, 0, cb, prim_bbc, 0, totprim); + pbvh->totnode = 1; + build_sub(pbvh, 0, cb, prim_bbc, 0, totprim); } /** @@ -561,7 +566,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim) * \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH * (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply(). */ -void BKE_pbvh_build_mesh(PBVH *bvh, +void BKE_pbvh_build_mesh(PBVH *pbvh, const Mesh *mesh, const MPoly *mpoly, const MLoop *mloop, @@ -576,21 +581,21 @@ void BKE_pbvh_build_mesh(PBVH *bvh, BBC *prim_bbc = NULL; BB cb; - bvh->mesh = mesh; - bvh->type = PBVH_FACES; - bvh->mpoly = mpoly; - bvh->mloop = mloop; - bvh->looptri = looptri; - bvh->verts = verts; - bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap"); - bvh->totvert = totvert; - bvh->leaf_limit = LEAF_LIMIT; - bvh->vdata = vdata; - bvh->ldata = ldata; - bvh->pdata = pdata; - - bvh->face_sets_color_seed = mesh->face_sets_color_seed; - bvh->face_sets_color_default = mesh->face_sets_color_default; + pbvh->mesh = mesh; + pbvh->type = PBVH_FACES; + pbvh->mpoly = mpoly; + pbvh->mloop = mloop; + pbvh->looptri = looptri; + pbvh->verts = verts; + pbvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap"); + pbvh->totvert = totvert; + pbvh->leaf_limit = LEAF_LIMIT; + pbvh->vdata = vdata; + pbvh->ldata = ldata; + pbvh->pdata = pdata; + + pbvh->face_sets_color_seed = mesh->face_sets_color_seed; + pbvh->face_sets_color_default = mesh->face_sets_color_default; BB_reset(&cb); @@ -605,7 +610,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh, BB_reset((BB *)bbc); for (int j = 0; j < sides; j++) { - BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co); + BB_expand((BB *)bbc, verts[pbvh->mloop[lt->tri[j]].v].co); } BBC_update_centroid(bbc); @@ -614,15 +619,15 @@ void BKE_pbvh_build_mesh(PBVH *bvh, } if (looptri_num) { - pbvh_build(bvh, &cb, prim_bbc, looptri_num); + pbvh_build(pbvh, &cb, prim_bbc, looptri_num); } MEM_freeN(prim_bbc); - MEM_freeN(bvh->vert_bitmap); + MEM_freeN(pbvh->vert_bitmap); } /* Do a full rebuild with on Grids data structure */ -void BKE_pbvh_build_grids(PBVH *bvh, +void BKE_pbvh_build_grids(PBVH *pbvh, CCGElem **grids, int totgrid, CCGKey *key, @@ -632,14 +637,14 @@ void BKE_pbvh_build_grids(PBVH *bvh, { const int gridsize = key->grid_size; - bvh->type = PBVH_GRIDS; - bvh->grids = grids; - bvh->gridfaces = gridfaces; - bvh->grid_flag_mats = flagmats; - bvh->totgrid = totgrid; - bvh->gridkey = *key; - bvh->grid_hidden = grid_hidden; - bvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1); + pbvh->type = PBVH_GRIDS; + pbvh->grids = grids; + pbvh->gridfaces = gridfaces; + pbvh->grid_flag_mats = flagmats; + pbvh->totgrid = totgrid; + pbvh->gridkey = *key; + pbvh->grid_hidden = grid_hidden; + pbvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1); BB cb; BB_reset(&cb); @@ -663,7 +668,7 @@ void BKE_pbvh_build_grids(PBVH *bvh, } if (totgrid) { - pbvh_build(bvh, &cb, prim_bbc, totgrid); + pbvh_build(pbvh, &cb, prim_bbc, totgrid); } MEM_freeN(prim_bbc); @@ -671,15 +676,15 @@ void BKE_pbvh_build_grids(PBVH *bvh, PBVH *BKE_pbvh_new(void) { - PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh"); - bvh->respect_hide = true; - return bvh; + PBVH *pbvh = MEM_callocN(sizeof(PBVH), "pbvh"); + pbvh->respect_hide = true; + return pbvh; } -void BKE_pbvh_free(PBVH *bvh) +void BKE_pbvh_free(PBVH *pbvh) { - for (int i = 0; i < bvh->totnode; i++) { - PBVHNode *node = &bvh->nodes[i]; + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *node = &pbvh->nodes[i]; if (node->flag & PBVH_Leaf) { if (node->draw_buffers) { @@ -703,42 +708,42 @@ void BKE_pbvh_free(PBVH *bvh) } } - if (bvh->deformed) { - if (bvh->verts) { + if (pbvh->deformed) { + if (pbvh->verts) { /* if pbvh was deformed, new memory was allocated for verts/faces -- free it */ - MEM_freeN((void *)bvh->verts); + MEM_freeN((void *)pbvh->verts); } } - if (bvh->looptri) { - MEM_freeN((void *)bvh->looptri); + if (pbvh->looptri) { + MEM_freeN((void *)pbvh->looptri); } - if (bvh->nodes) { - MEM_freeN(bvh->nodes); + if (pbvh->nodes) { + MEM_freeN(pbvh->nodes); } - if (bvh->prim_indices) { - MEM_freeN(bvh->prim_indices); + if (pbvh->prim_indices) { + MEM_freeN(pbvh->prim_indices); } - MEM_freeN(bvh); + MEM_freeN(pbvh); } static void pbvh_iter_begin(PBVHIter *iter, - PBVH *bvh, + PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data) { - iter->bvh = bvh; + iter->pbvh = pbvh; iter->scb = scb; iter->search_data = search_data; iter->stack = iter->stackfixed; iter->stackspace = STACK_FIXED_DEPTH; - iter->stack[0].node = bvh->nodes; + iter->stack[0].node = pbvh->nodes; iter->stack[0].revisiting = false; iter->stacksize = 1; } @@ -804,8 +809,8 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter) pbvh_stack_push(iter, node, true); /* push two child nodes on the stack */ - pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false); - pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false); + pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false); + pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false); } } @@ -834,8 +839,8 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter) return node; } else { - pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false); - pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false); + pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false); + pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false); } } @@ -843,13 +848,13 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter) } void BKE_pbvh_search_gather( - PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot) + PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot) { PBVHIter iter; PBVHNode **array = NULL, *node; int tot = 0, space = 0; - pbvh_iter_begin(&iter, bvh, scb, search_data); + pbvh_iter_begin(&iter, pbvh, scb, search_data); while ((node = pbvh_iter_next(&iter))) { if (node->flag & PBVH_Leaf) { @@ -875,7 +880,7 @@ void BKE_pbvh_search_gather( *r_tot = tot; } -void BKE_pbvh_search_callback(PBVH *bvh, +void BKE_pbvh_search_callback(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, BKE_pbvh_HitCallback hcb, @@ -884,7 +889,7 @@ void BKE_pbvh_search_callback(PBVH *bvh, PBVHIter iter; PBVHNode *node; - pbvh_iter_begin(&iter, bvh, scb, search_data); + pbvh_iter_begin(&iter, pbvh, scb, search_data); while ((node = pbvh_iter_next(&iter))) { if (node->flag & PBVH_Leaf) { @@ -958,7 +963,7 @@ float BKE_pbvh_node_get_tmin(PBVHNode *node) return node->tmin; } -static void BKE_pbvh_search_callback_occluded(PBVH *bvh, +static void BKE_pbvh_search_callback_occluded(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, BKE_pbvh_HitOccludedCallback hcb, @@ -968,7 +973,7 @@ static void BKE_pbvh_search_callback_occluded(PBVH *bvh, PBVHNode *node; node_tree *tree = NULL; - pbvh_iter_begin(&iter, bvh, scb, search_data); + pbvh_iter_begin(&iter, pbvh, scb, search_data); while ((node = pbvh_iter_next_occluded(&iter))) { if (node->flag & PBVH_Leaf) { @@ -1009,7 +1014,7 @@ static bool update_search_cb(PBVHNode *node, void *data_v) } typedef struct PBVHUpdateData { - PBVH *bvh; + PBVH *pbvh; PBVHNode **nodes; int totnode; @@ -1024,7 +1029,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, { PBVHUpdateData *data = userdata; - PBVH *bvh = data->bvh; + PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; float(*vnors)[3] = data->vnors; @@ -1036,25 +1041,25 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, const int totface = node->totprim; for (int i = 0; i < totface; i++) { - const MLoopTri *lt = &bvh->looptri[faces[i]]; + const MLoopTri *lt = &pbvh->looptri[faces[i]]; const unsigned int vtri[3] = { - bvh->mloop[lt->tri[0]].v, - bvh->mloop[lt->tri[1]].v, - bvh->mloop[lt->tri[2]].v, + pbvh->mloop[lt->tri[0]].v, + pbvh->mloop[lt->tri[1]].v, + pbvh->mloop[lt->tri[2]].v, }; const int sides = 3; /* Face normal and mask */ if (lt->poly != mpoly_prev) { - const MPoly *mp = &bvh->mpoly[lt->poly]; - BKE_mesh_calc_poly_normal(mp, &bvh->mloop[mp->loopstart], bvh->verts, fn); + const MPoly *mp = &pbvh->mpoly[lt->poly]; + BKE_mesh_calc_poly_normal(mp, &pbvh->mloop[mp->loopstart], pbvh->verts, fn); mpoly_prev = lt->poly; } for (int j = sides; j--;) { const int v = vtri[j]; - if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) { + if (pbvh->verts[v].flag & ME_VERT_PBVH_UPDATE) { /* Note: This avoids `lock, add_v3_v3, unlock` * and is five to ten times quicker than a spin-lock. * Not exact equivalent though, since atomicity is only ensured for one component @@ -1073,7 +1078,7 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata, const TaskParallelTLS *__restrict UNUSED(tls)) { PBVHUpdateData *data = userdata; - PBVH *bvh = data->bvh; + PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; float(*vnors)[3] = data->vnors; @@ -1083,7 +1088,7 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata, for (int i = 0; i < totvert; i++) { const int v = verts[i]; - MVert *mvert = &bvh->verts[v]; + MVert *mvert = &pbvh->verts[v]; /* No atomics necessary because we are iterating over uniq_verts only, * so we know only this thread will handle this vertex. */ @@ -1098,11 +1103,11 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata, } } -static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode) +static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode) { /* could be per node to save some memory, but also means * we have to store for each vertex which node it is in */ - float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bvh->totvert, __func__); + float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * pbvh->totvert, __func__); /* subtle assumptions: * - We know that for all edited vertices, the nodes with faces @@ -1115,7 +1120,7 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode) */ PBVHUpdateData data = { - .bvh = bvh, + .pbvh = pbvh, .nodes = nodes, .vnors = vnors, }; @@ -1135,7 +1140,7 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata, { PBVHUpdateData *data = userdata; - PBVH *bvh = data->bvh; + PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; if (node->flag & PBVH_UpdateMask) { @@ -1144,7 +1149,7 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata, if (node->flag & PBVH_Leaf) { PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL) + BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL) { if (vd.mask && *vd.mask < 1.0f) { has_unmasked = true; @@ -1166,10 +1171,10 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata, } } -static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) +static void pbvh_update_mask_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag) { PBVHUpdateData data = { - .bvh = bvh, + .pbvh = pbvh, .nodes = nodes, .flag = flag, }; @@ -1185,14 +1190,14 @@ static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata, { PBVHUpdateData *data = userdata; - PBVH *bvh = data->bvh; + PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; if (node->flag & PBVH_UpdateVisibility) { node->flag &= ~PBVH_UpdateVisibility; BKE_pbvh_node_fully_hidden_set(node, true); if (node->flag & PBVH_Leaf) { PBVHVertexIter vd; - BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL) + BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL) { if (vd.visible) { BKE_pbvh_node_fully_hidden_set(node, false); @@ -1204,10 +1209,10 @@ static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata, } } -static void pbvh_update_visibility_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) +static void pbvh_update_visibility_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag) { PBVHUpdateData data = { - .bvh = bvh, + .pbvh = pbvh, .nodes = nodes, .flag = flag, }; @@ -1222,14 +1227,14 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata, const TaskParallelTLS *__restrict UNUSED(tls)) { PBVHUpdateData *data = userdata; - PBVH *bvh = data->bvh; + PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; const int flag = data->flag; if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB)) { /* don't clear flag yet, leave it for flushing later */ /* Note that bvh usage is read-only here, so no need to thread-protect it. */ - update_node_vb(bvh, node); + update_node_vb(pbvh, node); } if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB)) { @@ -1241,11 +1246,11 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata, } } -void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) +void pbvh_update_BB_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag) { /* update BB, redraw flag */ PBVHUpdateData data = { - .bvh = bvh, + .pbvh = pbvh, .nodes = nodes, .flag = flag, }; @@ -1255,7 +1260,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings); } -static int pbvh_get_buffers_update_flags(PBVH *UNUSED(bvh)) +static int pbvh_get_buffers_update_flags(PBVH *UNUSED(pbvh)) { int update_flags = GPU_PBVH_BUFFERS_SHOW_VCOL | GPU_PBVH_BUFFERS_SHOW_MASK | GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS; @@ -1270,61 +1275,61 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, * do any OpenGL calls. Flags are not cleared immediately, that happens * after GPU_pbvh_buffer_flush() which does the final OpenGL calls. */ PBVHUpdateData *data = userdata; - PBVH *bvh = data->bvh; + PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; if (node->flag & PBVH_RebuildDrawBuffers) { - switch (bvh->type) { + switch (pbvh->type) { case PBVH_GRIDS: - node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, bvh->grid_hidden); + node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, pbvh->grid_hidden); break; case PBVH_FACES: node->draw_buffers = GPU_pbvh_mesh_buffers_build( - bvh->mpoly, - bvh->mloop, - bvh->looptri, - bvh->verts, + pbvh->mpoly, + pbvh->mloop, + pbvh->looptri, + pbvh->verts, node->prim_indices, - CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS), + CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS), node->totprim, - bvh->mesh); + pbvh->mesh); break; case PBVH_BMESH: - node->draw_buffers = GPU_pbvh_bmesh_buffers_build(bvh->flags & + node->draw_buffers = GPU_pbvh_bmesh_buffers_build(pbvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING); break; } } if (node->flag & PBVH_UpdateDrawBuffers) { - const int update_flags = pbvh_get_buffers_update_flags(bvh); - switch (bvh->type) { + const int update_flags = pbvh_get_buffers_update_flags(pbvh); + switch (pbvh->type) { case PBVH_GRIDS: GPU_pbvh_grid_buffers_update(node->draw_buffers, - bvh->subdiv_ccg, - bvh->grids, - bvh->grid_flag_mats, + pbvh->subdiv_ccg, + pbvh->grids, + pbvh->grid_flag_mats, node->prim_indices, node->totprim, - bvh->face_sets, - bvh->face_sets_color_seed, - bvh->face_sets_color_default, - &bvh->gridkey, + pbvh->face_sets, + pbvh->face_sets_color_seed, + pbvh->face_sets_color_default, + &pbvh->gridkey, update_flags); break; case PBVH_FACES: GPU_pbvh_mesh_buffers_update(node->draw_buffers, - bvh->verts, - CustomData_get_layer(bvh->vdata, CD_PAINT_MASK), - CustomData_get_layer(bvh->ldata, CD_MLOOPCOL), - CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS), - bvh->face_sets_color_seed, - bvh->face_sets_color_default, + pbvh->verts, + CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK), + CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL), + CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS), + pbvh->face_sets_color_seed, + pbvh->face_sets_color_default, update_flags); break; case PBVH_BMESH: GPU_pbvh_bmesh_buffers_update(node->draw_buffers, - bvh->bm, + pbvh->bm, node->bm_faces, node->bm_unique_verts, node->bm_other_verts, @@ -1334,9 +1339,9 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata, } } -static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, int update_flag) +static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag) { - if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(bvh->type, PBVH_GRIDS, PBVH_BMESH)) { + if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) { /* Free buffers uses OpenGL, so not in parallel. */ for (int n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; @@ -1345,11 +1350,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i node->draw_buffers = NULL; } else if ((node->flag & PBVH_UpdateDrawBuffers) && node->draw_buffers) { - if (bvh->type == PBVH_GRIDS) { + if (pbvh->type == PBVH_GRIDS) { GPU_pbvh_grid_buffers_update_free( - node->draw_buffers, bvh->grid_flag_mats, node->prim_indices); + node->draw_buffers, pbvh->grid_flag_mats, node->prim_indices); } - else if (bvh->type == PBVH_BMESH) { + else if (pbvh->type == PBVH_BMESH) { GPU_pbvh_bmesh_buffers_update_free(node->draw_buffers); } } @@ -1358,7 +1363,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i /* Parallel creation and update of draw buffers. */ PBVHUpdateData data = { - .bvh = bvh, + .pbvh = pbvh, .nodes = nodes, }; @@ -1367,7 +1372,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings); } -static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) +static int pbvh_flush_bb(PBVH *pbvh, PBVHNode *node, int flag) { int update = 0; @@ -1386,11 +1391,11 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) return update; } else { - update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset, flag); - update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset + 1, flag); + update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset, flag); + update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset + 1, flag); if (update & PBVH_UpdateBB) { - update_node_vb(bvh, node); + update_node_vb(pbvh, node); } if (update & PBVH_UpdateOriginalBB) { node->orig_vb = node->vb; @@ -1400,45 +1405,45 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) return update; } -void BKE_pbvh_update_bounds(PBVH *bvh, int flag) +void BKE_pbvh_update_bounds(PBVH *pbvh, int flag) { - if (!bvh->nodes) { + if (!pbvh->nodes) { return; } PBVHNode **nodes; int totnode; - BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode); if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw)) { - pbvh_update_BB_redraw(bvh, nodes, totnode, flag); + pbvh_update_BB_redraw(pbvh, nodes, totnode, flag); } if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB)) { - pbvh_flush_bb(bvh, bvh->nodes, flag); + pbvh_flush_bb(pbvh, pbvh->nodes, flag); } MEM_SAFE_FREE(nodes); } -void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag) +void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag) { - if (!bvh->nodes) { + if (!pbvh->nodes) { return; } PBVHNode **nodes; int totnode; - BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode); if (flag & (PBVH_UpdateMask)) { - pbvh_update_mask_redraw(bvh, nodes, totnode, flag); + pbvh_update_mask_redraw(pbvh, nodes, totnode, flag); } if (flag & (PBVH_UpdateVisibility)) { - pbvh_update_visibility_redraw(bvh, nodes, totnode, flag); + pbvh_update_visibility_redraw(pbvh, nodes, totnode, flag); } if (nodes) { @@ -1446,13 +1451,13 @@ void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag) } } -static void pbvh_faces_node_visibility_update(PBVH *bvh, PBVHNode *node) +static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node) { MVert *mvert; const int *vert_indices; int totvert, i; - BKE_pbvh_node_num_verts(bvh, node, NULL, &totvert); - BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &mvert); + BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert); + BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert); for (i = 0; i < totvert; i++) { MVert *v = &mvert[vert_indices[i]]; @@ -1465,15 +1470,15 @@ static void pbvh_faces_node_visibility_update(PBVH *bvh, PBVHNode *node) BKE_pbvh_node_fully_hidden_set(node, true); } -static void pbvh_grids_node_visibility_update(PBVH *bvh, PBVHNode *node) +static void pbvh_grids_node_visibility_update(PBVH *pbvh, PBVHNode *node) { CCGElem **grids; BLI_bitmap **grid_hidden; int *grid_indices, totgrid, i; - BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, NULL, &grids); - grid_hidden = BKE_pbvh_grid_hidden(bvh); - CCGKey key = *BKE_pbvh_get_grid_key(bvh); + BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, &grids); + grid_hidden = BKE_pbvh_grid_hidden(pbvh); + CCGKey key = *BKE_pbvh_get_grid_key(pbvh); for (i = 0; i < totgrid; i++) { int g = grid_indices[i], x, y; @@ -1530,15 +1535,15 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata, { PBVHUpdateData *data = userdata; - PBVH *bvh = data->bvh; + PBVH *pbvh = data->pbvh; PBVHNode *node = data->nodes[n]; if (node->flag & PBVH_UpdateMask) { - switch (BKE_pbvh_type(bvh)) { + switch (BKE_pbvh_type(pbvh)) { case PBVH_FACES: - pbvh_faces_node_visibility_update(bvh, node); + pbvh_faces_node_visibility_update(pbvh, node); break; case PBVH_GRIDS: - pbvh_grids_node_visibility_update(bvh, node); + pbvh_grids_node_visibility_update(pbvh, node); break; case PBVH_BMESH: pbvh_bmesh_node_visibility_update(node); @@ -1548,10 +1553,10 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata, } } -static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode) +static void pbvh_update_visibility(PBVH *pbvh, PBVHNode **nodes, int totnode) { PBVHUpdateData data = { - .bvh = bvh, + .pbvh = pbvh, .nodes = nodes, }; @@ -1560,9 +1565,9 @@ static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode) BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings); } -void BKE_pbvh_update_visibility(PBVH *bvh) +void BKE_pbvh_update_visibility(PBVH *pbvh) { - if (!bvh->nodes) { + if (!pbvh->nodes) { return; } @@ -1570,15 +1575,15 @@ void BKE_pbvh_update_visibility(PBVH *bvh) int totnode; BKE_pbvh_search_gather( - bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode); - pbvh_update_visibility(bvh, nodes, totnode); + pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode); + pbvh_update_visibility(pbvh, nodes, totnode); if (nodes) { MEM_freeN(nodes); } } -void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) +void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]) { PBVHIter iter; PBVHNode *node; @@ -1586,7 +1591,7 @@ void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) BB_reset(&bb); - pbvh_iter_begin(&iter, bvh, NULL, NULL); + pbvh_iter_begin(&iter, pbvh, NULL, NULL); while ((node = pbvh_iter_next(&iter))) { if (node->flag & PBVH_UpdateRedraw) { @@ -1600,18 +1605,18 @@ void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]) copy_v3_v3(bb_max, bb.bmax); } -void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface) +void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface) { GSet *face_set = BLI_gset_ptr_new(__func__); PBVHNode *node; PBVHIter iter; - pbvh_iter_begin(&iter, bvh, NULL, NULL); + pbvh_iter_begin(&iter, pbvh, NULL, NULL); while ((node = pbvh_iter_next(&iter))) { if (node->flag & PBVH_UpdateNormals) { for (uint i = 0; i < node->totprim; i++) { - void *face = bvh->gridfaces[node->prim_indices[i]]; + void *face = pbvh->gridfaces[node->prim_indices[i]]; BLI_gset_add(face_set, face); } @@ -1647,25 +1652,25 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int * /***************************** PBVH Access ***********************************/ -PBVHType BKE_pbvh_type(const PBVH *bvh) +PBVHType BKE_pbvh_type(const PBVH *pbvh) { - return bvh->type; + return pbvh->type; } -bool BKE_pbvh_has_faces(const PBVH *bvh) +bool BKE_pbvh_has_faces(const PBVH *pbvh) { - if (bvh->type == PBVH_BMESH) { - return (bvh->bm->totface != 0); + if (pbvh->type == PBVH_BMESH) { + return (pbvh->bm->totface != 0); } else { - return (bvh->totprim != 0); + return (pbvh->totprim != 0); } } -void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]) +void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]) { - if (bvh->totnode) { - const BB *bb = &bvh->nodes[0].vb; + if (pbvh->totnode) { + const BB *bb = &pbvh->nodes[0].vb; copy_v3_v3(min, bb->bmin); copy_v3_v3(max, bb->bmax); } @@ -1675,34 +1680,40 @@ void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]) } } -BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *bvh) +BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *pbvh) { - BLI_assert(bvh->type == PBVH_GRIDS); - return bvh->grid_hidden; + BLI_assert(pbvh->type == PBVH_GRIDS); + return pbvh->grid_hidden; } -const CCGKey *BKE_pbvh_get_grid_key(const PBVH *bvh) +const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh) { - BLI_assert(bvh->type == PBVH_GRIDS); - return &bvh->gridkey; + BLI_assert(pbvh->type == PBVH_GRIDS); + return &pbvh->gridkey; } -struct CCGElem **BKE_pbvh_get_grids(const PBVH *bvh) +struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh) { - BLI_assert(bvh->type == PBVH_GRIDS); - return bvh->grids; + BLI_assert(pbvh->type == PBVH_GRIDS); + return pbvh->grids; } -int BKE_pbvh_get_grid_num_vertices(const PBVH *bvh) +BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh) { - BLI_assert(bvh->type == PBVH_GRIDS); - return bvh->totgrid * bvh->gridkey.grid_area; + BLI_assert(pbvh->type == PBVH_GRIDS); + return pbvh->grid_hidden; } -BMesh *BKE_pbvh_get_bmesh(PBVH *bvh) +int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh) { - BLI_assert(bvh->type == PBVH_BMESH); - return bvh->bm; + BLI_assert(pbvh->type == PBVH_GRIDS); + return pbvh->totgrid * pbvh->gridkey.grid_area; +} + +BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh) +{ + BLI_assert(pbvh->type == PBVH_BMESH); + return pbvh->bm; } /***************************** Node Access ***********************************/ @@ -1785,7 +1796,7 @@ bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node) return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyUnmasked); } -void BKE_pbvh_node_get_verts(PBVH *bvh, +void BKE_pbvh_node_get_verts(PBVH *pbvh, PBVHNode *node, const int **r_vert_indices, MVert **r_verts) @@ -1795,17 +1806,17 @@ void BKE_pbvh_node_get_verts(PBVH *bvh, } if (r_verts) { - *r_verts = bvh->verts; + *r_verts = pbvh->verts; } } -void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *r_totvert) +void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert) { int tot; - switch (bvh->type) { + switch (pbvh->type) { case PBVH_GRIDS: - tot = node->totprim * bvh->gridkey.grid_area; + tot = node->totprim * pbvh->gridkey.grid_area; if (r_totvert) { *r_totvert = tot; } @@ -1833,7 +1844,7 @@ void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int * } } -void BKE_pbvh_node_get_grids(PBVH *bvh, +void BKE_pbvh_node_get_grids(PBVH *pbvh, PBVHNode *node, int **r_grid_indices, int *r_totgrid, @@ -1841,7 +1852,7 @@ void BKE_pbvh_node_get_grids(PBVH *bvh, int *r_gridsize, CCGElem ***r_griddata) { - switch (bvh->type) { + switch (pbvh->type) { case PBVH_GRIDS: if (r_grid_indices) { *r_grid_indices = node->prim_indices; @@ -1850,13 +1861,13 @@ void BKE_pbvh_node_get_grids(PBVH *bvh, *r_totgrid = node->totprim; } if (r_maxgrid) { - *r_maxgrid = bvh->totgrid; + *r_maxgrid = pbvh->totgrid; } if (r_gridsize) { - *r_gridsize = bvh->gridkey.grid_size; + *r_gridsize = pbvh->gridkey.grid_size; } if (r_griddata) { - *r_griddata = bvh->grids; + *r_griddata = pbvh->grids; } break; case PBVH_FACES: @@ -1927,15 +1938,15 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node, * however this is important to avoid having to recalculate bound-box & sync the buffers to the * GPU (which is far more expensive!) See: T47232. */ -bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node) +bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node) { - BLI_assert(bvh->type == PBVH_FACES); + BLI_assert(pbvh->type == PBVH_FACES); const int *verts = node->vert_indices; const int totvert = node->uniq_verts + node->face_verts; for (int i = 0; i < totvert; i++) { const int v = verts[i]; - const MVert *mvert = &bvh->verts[v]; + const MVert *mvert = &pbvh->verts[v]; if (mvert->flag & ME_VERT_PBVH_UPDATE) { return true; @@ -1971,7 +1982,7 @@ static bool ray_aabb_intersect(PBVHNode *node, void *data_v) return isect_ray_aabb_v3(&rcd->ray, bb_min, bb_max, &node->tmin); } -void BKE_pbvh_raycast(PBVH *bvh, +void BKE_pbvh_raycast(PBVH *pbvh, BKE_pbvh_HitOccludedCallback cb, void *data, const float ray_start[3], @@ -1983,7 +1994,7 @@ void BKE_pbvh_raycast(PBVH *bvh, isect_ray_aabb_v3_precalc(&rcd.ray, ray_start, ray_normal); rcd.original = original; - BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data); + BKE_pbvh_search_callback_occluded(pbvh, ray_aabb_intersect, &rcd, cb, data); } bool ray_face_intersection_quad(const float ray_start[3], @@ -2101,7 +2112,7 @@ bool ray_face_nearest_tri(const float ray_start[3], } } -static bool pbvh_faces_node_raycast(PBVH *bvh, +static bool pbvh_faces_node_raycast(PBVH *pbvh, const PBVHNode *node, float (*origco)[3], const float ray_start[3], @@ -2112,18 +2123,18 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, int *r_active_face_index, float *r_face_normal) { - const MVert *vert = bvh->verts; - const MLoop *mloop = bvh->mloop; + const MVert *vert = pbvh->verts; + const MLoop *mloop = pbvh->mloop; const int *faces = node->prim_indices; int totface = node->totprim; bool hit = false; float nearest_vertex_co[3] = {0.0f}; for (int i = 0; i < totface; i++) { - const MLoopTri *lt = &bvh->looptri[faces[i]]; + const MLoopTri *lt = &pbvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { + if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { continue; } @@ -2169,7 +2180,7 @@ static bool pbvh_faces_node_raycast(PBVH *bvh, return hit; } -static bool pbvh_grids_node_raycast(PBVH *bvh, +static bool pbvh_grids_node_raycast(PBVH *pbvh, PBVHNode *node, float (*origco)[3], const float ray_start[3], @@ -2181,21 +2192,21 @@ static bool pbvh_grids_node_raycast(PBVH *bvh, float *r_face_normal) { const int totgrid = node->totprim; - const int gridsize = bvh->gridkey.grid_size; + const int gridsize = pbvh->gridkey.grid_size; bool hit = false; float nearest_vertex_co[3] = {0.0}; - const CCGKey *gridkey = &bvh->gridkey; + const CCGKey *gridkey = &pbvh->gridkey; for (int i = 0; i < totgrid; i++) { const int grid_index = node->prim_indices[i]; - CCGElem *grid = bvh->grids[grid_index]; + CCGElem *grid = pbvh->grids[grid_index]; BLI_bitmap *gh; if (!grid) { continue; } - gh = bvh->grid_hidden[grid_index]; + gh = pbvh->grid_hidden[grid_index]; for (int y = 0; y < gridsize - 1; y++) { for (int x = 0; x < gridsize - 1; x++) { @@ -2263,7 +2274,7 @@ static bool pbvh_grids_node_raycast(PBVH *bvh, return hit; } -bool BKE_pbvh_node_raycast(PBVH *bvh, +bool BKE_pbvh_node_raycast(PBVH *pbvh, PBVHNode *node, float (*origco)[3], bool use_origco, @@ -2281,9 +2292,9 @@ bool BKE_pbvh_node_raycast(PBVH *bvh, return false; } - switch (bvh->type) { + switch (pbvh->type) { case PBVH_FACES: - hit |= pbvh_faces_node_raycast(bvh, + hit |= pbvh_faces_node_raycast(pbvh, node, origco, ray_start, @@ -2295,7 +2306,7 @@ bool BKE_pbvh_node_raycast(PBVH *bvh, face_normal); break; case PBVH_GRIDS: - hit |= pbvh_grids_node_raycast(bvh, + hit |= pbvh_grids_node_raycast(pbvh, node, origco, ray_start, @@ -2307,7 +2318,7 @@ bool BKE_pbvh_node_raycast(PBVH *bvh, face_normal); break; case PBVH_BMESH: - BM_mesh_elem_index_ensure(bvh->bm, BM_VERT); + BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT); hit = pbvh_bmesh_node_raycast(node, ray_start, ray_normal, @@ -2323,9 +2334,9 @@ bool BKE_pbvh_node_raycast(PBVH *bvh, } void BKE_pbvh_raycast_project_ray_root( - PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]) + PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]) { - if (bvh->nodes) { + if (pbvh->nodes) { float rootmin_start, rootmin_end; float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3]; struct IsectRayAABB_Precalc ray; @@ -2334,10 +2345,10 @@ void BKE_pbvh_raycast_project_ray_root( float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f}; if (original) { - BKE_pbvh_node_get_original_BB(bvh->nodes, bb_min_root, bb_max_root); + BKE_pbvh_node_get_original_BB(pbvh->nodes, bb_min_root, bb_max_root); } else { - BKE_pbvh_node_get_BB(bvh->nodes, bb_min_root, bb_max_root); + BKE_pbvh_node_get_BB(pbvh->nodes, bb_min_root, bb_max_root); } /* Slightly offset min and max in case we have a zero width node @@ -2399,7 +2410,7 @@ static bool nearest_to_ray_aabb_dist_sq(PBVHNode *node, void *data_v) return depth > 0.0f; } -void BKE_pbvh_find_nearest_to_ray(PBVH *bvh, +void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh, BKE_pbvh_SearchNearestCallback cb, void *data, const float ray_start[3], @@ -2411,10 +2422,10 @@ void BKE_pbvh_find_nearest_to_ray(PBVH *bvh, dist_squared_ray_to_aabb_v3_precalc(&ncd.dist_ray_to_aabb_precalc, ray_start, ray_normal); ncd.original = original; - BKE_pbvh_search_callback_occluded(bvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data); + BKE_pbvh_search_callback_occluded(pbvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data); } -static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh, +static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh, const PBVHNode *node, float (*origco)[3], const float ray_start[3], @@ -2422,17 +2433,17 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh, float *depth, float *dist_sq) { - const MVert *vert = bvh->verts; - const MLoop *mloop = bvh->mloop; + const MVert *vert = pbvh->verts; + const MLoop *mloop = pbvh->mloop; const int *faces = node->prim_indices; int i, totface = node->totprim; bool hit = false; for (i = 0; i < totface; i++) { - const MLoopTri *lt = &bvh->looptri[faces[i]]; + const MLoopTri *lt = &pbvh->looptri[faces[i]]; const int *face_verts = node->face_vert_indices[i]; - if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { + if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) { continue; } @@ -2461,7 +2472,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh, return hit; } -static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh, +static bool pbvh_grids_node_nearest_to_ray(PBVH *pbvh, PBVHNode *node, float (*origco)[3], const float ray_start[3], @@ -2470,18 +2481,18 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh, float *dist_sq) { const int totgrid = node->totprim; - const int gridsize = bvh->gridkey.grid_size; + const int gridsize = pbvh->gridkey.grid_size; bool hit = false; for (int i = 0; i < totgrid; i++) { - CCGElem *grid = bvh->grids[node->prim_indices[i]]; + CCGElem *grid = pbvh->grids[node->prim_indices[i]]; BLI_bitmap *gh; if (!grid) { continue; } - gh = bvh->grid_hidden[node->prim_indices[i]]; + gh = pbvh->grid_hidden[node->prim_indices[i]]; for (int y = 0; y < gridsize - 1; y++) { for (int x = 0; x < gridsize - 1; x++) { @@ -2505,10 +2516,10 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh, else { hit |= ray_face_nearest_quad(ray_start, ray_normal, - CCG_grid_elem_co(&bvh->gridkey, grid, x, y), - CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y), - CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1), - CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1), + CCG_grid_elem_co(&pbvh->gridkey, grid, x, y), + CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y), + CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y + 1), + CCG_grid_elem_co(&pbvh->gridkey, grid, x, y + 1), depth, dist_sq); } @@ -2523,7 +2534,7 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh, return hit; } -bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh, +bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh, PBVHNode *node, float (*origco)[3], bool use_origco, @@ -2538,14 +2549,14 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh, return false; } - switch (bvh->type) { + switch (pbvh->type) { case PBVH_FACES: hit |= pbvh_faces_node_nearest_to_ray( - bvh, node, origco, ray_start, ray_normal, depth, dist_sq); + pbvh, node, origco, ray_start, ray_normal, depth, dist_sq); break; case PBVH_GRIDS: hit |= pbvh_grids_node_nearest_to_ray( - bvh, node, origco, ray_start, ray_normal, depth, dist_sq); + pbvh, node, origco, ray_start, ray_normal, depth, dist_sq); break; case PBVH_BMESH: hit = pbvh_bmesh_node_nearest_to_ray( @@ -2619,26 +2630,26 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data) return test_frustum_aabb(bb_min, bb_max, data) != ISECT_INSIDE; } -void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg) +void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg) { /* Update normals */ PBVHNode **nodes; int totnode; BKE_pbvh_search_gather( - bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode); + pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode); if (totnode > 0) { - if (bvh->type == PBVH_BMESH) { + if (pbvh->type == PBVH_BMESH) { pbvh_bmesh_normals_update(nodes, totnode); } - else if (bvh->type == PBVH_FACES) { - pbvh_faces_update_normals(bvh, nodes, totnode); + else if (pbvh->type == PBVH_FACES) { + pbvh_faces_update_normals(pbvh, nodes, totnode); } - else if (bvh->type == PBVH_GRIDS) { + else if (pbvh->type == PBVH_GRIDS) { struct CCGFace **faces; int num_faces; - BKE_pbvh_get_grid_updates(bvh, true, (void ***)&faces, &num_faces); + BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces); if (num_faces > 0) { BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces); MEM_freeN(faces); @@ -2649,10 +2660,10 @@ void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg) MEM_SAFE_FREE(nodes); } -void BKE_pbvh_face_sets_color_set(PBVH *bvh, int seed, int color_default) +void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default) { - bvh->face_sets_color_seed = seed; - bvh->face_sets_color_default = color_default; + pbvh->face_sets_color_seed = seed; + pbvh->face_sets_color_default = color_default; } /** @@ -2675,7 +2686,7 @@ static bool pbvh_draw_search_cb(PBVHNode *node, void *data_v) return true; } -void BKE_pbvh_draw_cb(PBVH *bvh, +void BKE_pbvh_draw_cb(PBVH *pbvh, bool update_only_visible, PBVHFrustumPlanes *update_frustum, PBVHFrustumPlanes *draw_frustum, @@ -2689,10 +2700,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh, if (!update_only_visible) { /* Update all draw buffers, also those outside the view. */ - BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode); + BKE_pbvh_search_gather( + pbvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode); if (totnode) { - pbvh_update_draw_buffers(bvh, nodes, totnode, update_flag); + pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag); } MEM_SAFE_FREE(nodes); @@ -2700,11 +2712,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh, /* Gather visible nodes. */ PBVHDrawSearchData data = {.frustum = update_frustum, .accum_update_flag = 0}; - BKE_pbvh_search_gather(bvh, pbvh_draw_search_cb, &data, &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &data, &nodes, &totnode); if (update_only_visible && (data.accum_update_flag & update_flag)) { /* Update draw buffers in visible nodes. */ - pbvh_update_draw_buffers(bvh, nodes, totnode, data.accum_update_flag); + pbvh_update_draw_buffers(pbvh, nodes, totnode, data.accum_update_flag); } /* Draw. */ @@ -2722,7 +2734,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh, MEM_SAFE_FREE(nodes); PBVHDrawSearchData draw_data = {.frustum = draw_frustum, .accum_update_flag = 0}; - BKE_pbvh_search_gather(bvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode); + BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode); for (int a = 0; a < totnode; a++) { PBVHNode *node = nodes[a]; @@ -2735,29 +2747,29 @@ void BKE_pbvh_draw_cb(PBVH *bvh, } void BKE_pbvh_draw_debug_cb( - PBVH *bvh, + PBVH *pbvh, void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag), void *user_data) { - for (int a = 0; a < bvh->totnode; a++) { - PBVHNode *node = &bvh->nodes[a]; + for (int a = 0; a < pbvh->totnode; a++) { + PBVHNode *node = &pbvh->nodes[a]; draw_fn(user_data, node->vb.bmin, node->vb.bmax, node->flag); } } void BKE_pbvh_grids_update( - PBVH *bvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden) + PBVH *pbvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden) { - bvh->grids = grids; - bvh->gridfaces = gridfaces; + pbvh->grids = grids; + pbvh->gridfaces = gridfaces; - if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) { - bvh->grid_flag_mats = flagmats; - bvh->grid_hidden = grid_hidden; + if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) { + pbvh->grid_flag_mats = flagmats; + pbvh->grid_hidden = grid_hidden; - for (int a = 0; a < bvh->totnode; a++) { - BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); + for (int a = 0; a < pbvh->totnode; a++) { + BKE_pbvh_node_mark_rebuild_draw(&pbvh->nodes[a]); } } } @@ -2830,7 +2842,7 @@ bool BKE_pbvh_is_deformed(PBVH *pbvh) } /* Proxies */ -PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node) +PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node) { int index, totverts; @@ -2845,7 +2857,7 @@ PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node) node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy"); } - BKE_pbvh_node_num_verts(bvh, node, &totverts, NULL); + BKE_pbvh_node_num_verts(pbvh, node, &totverts, NULL); node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co"); return node->proxies + index; @@ -2893,7 +2905,7 @@ void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot) *r_tot = tot; } -void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode) +void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode) { struct CCGElem **grids; struct MVert *verts; @@ -2906,16 +2918,16 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo vi->fno = NULL; vi->mvert = NULL; - vi->respect_hide = bvh->respect_hide; - if (bvh->respect_hide == false) { + vi->respect_hide = pbvh->respect_hide; + if (pbvh->respect_hide == false) { /* The same value for all vertices. */ vi->visible = true; } - BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids); - BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert); - BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts); - vi->key = bvh->gridkey; + BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids); + BKE_pbvh_node_num_verts(pbvh, node, &uniq_verts, &totvert); + BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &verts); + vi->key = pbvh->gridkey; vi->grids = grids; vi->grid_indices = grid_indices; @@ -2931,45 +2943,45 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo vi->vert_indices = vert_indices; vi->mverts = verts; - if (bvh->type == PBVH_BMESH) { + if (pbvh->type == PBVH_BMESH) { BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts); BLI_gsetIterator_init(&vi->bm_other_verts, node->bm_other_verts); - vi->bm_vdata = &bvh->bm->vdata; + vi->bm_vdata = &pbvh->bm->vdata; vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK); } vi->gh = NULL; if (vi->grids && mode == PBVH_ITER_UNIQUE) { - vi->grid_hidden = bvh->grid_hidden; + vi->grid_hidden = pbvh->grid_hidden; } vi->mask = NULL; - if (bvh->type == PBVH_FACES) { - vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK); + if (pbvh->type == PBVH_FACES) { + vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK); } } -bool pbvh_has_mask(PBVH *bvh) +bool pbvh_has_mask(PBVH *pbvh) { - switch (bvh->type) { + switch (pbvh->type) { case PBVH_GRIDS: - return (bvh->gridkey.has_mask != 0); + return (pbvh->gridkey.has_mask != 0); case PBVH_FACES: - return (bvh->vdata && CustomData_get_layer(bvh->vdata, CD_PAINT_MASK)); + return (pbvh->vdata && CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK)); case PBVH_BMESH: - return (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1)); + return (pbvh->bm && (CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK) != -1)); } return false; } -bool pbvh_has_face_sets(PBVH *bvh) +bool pbvh_has_face_sets(PBVH *pbvh) { - switch (bvh->type) { + switch (pbvh->type) { case PBVH_GRIDS: - return (bvh->pdata && CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS)); + return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS)); case PBVH_FACES: - return (bvh->pdata && CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS)); + return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS)); case PBVH_BMESH: return false; } @@ -2977,29 +2989,29 @@ bool pbvh_has_face_sets(PBVH *bvh) return false; } -void pbvh_show_mask_set(PBVH *bvh, bool show_mask) +void pbvh_show_mask_set(PBVH *pbvh, bool show_mask) { - bvh->show_mask = show_mask; + pbvh->show_mask = show_mask; } -void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets) +void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets) { - bvh->show_face_sets = show_face_sets; + pbvh->show_face_sets = show_face_sets; } -void BKE_pbvh_set_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes) +void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes) { - bvh->num_planes = planes->num_planes; - for (int i = 0; i < bvh->num_planes; i++) { - copy_v4_v4(bvh->planes[i], planes->planes[i]); + pbvh->num_planes = planes->num_planes; + for (int i = 0; i < pbvh->num_planes; i++) { + copy_v4_v4(pbvh->planes[i], planes->planes[i]); } } -void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes) +void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes) { - planes->num_planes = bvh->num_planes; + planes->num_planes = pbvh->num_planes; for (int i = 0; i < planes->num_planes; i++) { - copy_v4_v4(planes->planes[i], bvh->planes[i]); + copy_v4_v4(planes->planes[i], pbvh->planes[i]); } } @@ -3011,23 +3023,23 @@ void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings, settings->use_threading = use_threading && totnode > 1; } -MVert *BKE_pbvh_get_verts(const PBVH *bvh) +MVert *BKE_pbvh_get_verts(const PBVH *pbvh) { - BLI_assert(bvh->type == PBVH_FACES); - return bvh->verts; + BLI_assert(pbvh->type == PBVH_FACES); + return pbvh->verts; } -void BKE_pbvh_subdiv_cgg_set(PBVH *bvh, SubdivCCG *subdiv_ccg) +void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg) { - bvh->subdiv_ccg = subdiv_ccg; + pbvh->subdiv_ccg = subdiv_ccg; } -void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets) +void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets) { - bvh->face_sets = face_sets; + pbvh->face_sets = face_sets; } -void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide) +void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide) { - bvh->respect_hide = respect_hide; + pbvh->respect_hide = respect_hide; } diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 73042222436..e87c7c8d46d 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -62,7 +62,7 @@ // #define USE_VERIFY #ifdef USE_VERIFY -static void pbvh_bmesh_verify(PBVH *bvh); +static void pbvh_bmesh_verify(PBVH *pbvh); #endif /** \name BMesh Utility API @@ -200,13 +200,13 @@ static BMVert *bm_vert_hash_lookup_chain(GHash *deleted_verts, BMVert *v) /****************************** Building ******************************/ /* Update node data after splitting */ -static void pbvh_bmesh_node_finalize(PBVH *bvh, +static void pbvh_bmesh_node_finalize(PBVH *pbvh, const int node_index, const int cd_vert_node_offset, const int cd_face_node_offset) { GSetIterator gs_iter; - PBVHNode *n = &bvh->nodes[node_index]; + PBVHNode *n = &pbvh->nodes[node_index]; bool has_visible = false; /* Create vert hash sets */ @@ -258,15 +258,15 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, } /* Recursively split the node if it exceeds the leaf_limit */ -static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_index) +static void pbvh_bmesh_node_split(PBVH *pbvh, const BBC *bbc_array, int node_index) { - const int cd_vert_node_offset = bvh->cd_vert_node_offset; - const int cd_face_node_offset = bvh->cd_face_node_offset; - PBVHNode *n = &bvh->nodes[node_index]; + const int cd_vert_node_offset = pbvh->cd_vert_node_offset; + const int cd_face_node_offset = pbvh->cd_face_node_offset; + PBVHNode *n = &pbvh->nodes[node_index]; - if (BLI_gset_len(n->bm_faces) <= bvh->leaf_limit) { + if (BLI_gset_len(n->bm_faces) <= pbvh->leaf_limit) { /* Node limit not exceeded */ - pbvh_bmesh_node_finalize(bvh, node_index, cd_vert_node_offset, cd_face_node_offset); + pbvh_bmesh_node_finalize(pbvh, node_index, cd_vert_node_offset, cd_face_node_offset); return; } @@ -286,15 +286,15 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde const float mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f; /* Add two new child nodes */ - const int children = bvh->totnode; + const int children = pbvh->totnode; n->children_offset = children; - pbvh_grow_nodes(bvh, bvh->totnode + 2); + pbvh_grow_nodes(pbvh, pbvh->totnode + 2); /* Array reallocated, update current node pointer */ - n = &bvh->nodes[node_index]; + n = &pbvh->nodes[node_index]; /* Initialize children */ - PBVHNode *c1 = &bvh->nodes[children], *c2 = &bvh->nodes[children + 1]; + PBVHNode *c1 = &pbvh->nodes[children], *c2 = &pbvh->nodes[children + 1]; c1->flag |= PBVH_Leaf; c2->flag |= PBVH_Leaf; c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_len(n->bm_faces) / 2); @@ -370,25 +370,25 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde n->flag &= ~PBVH_Leaf; /* Recurse */ - pbvh_bmesh_node_split(bvh, bbc_array, children); - pbvh_bmesh_node_split(bvh, bbc_array, children + 1); + pbvh_bmesh_node_split(pbvh, bbc_array, children); + pbvh_bmesh_node_split(pbvh, bbc_array, children + 1); /* Array maybe reallocated, update current node pointer */ - n = &bvh->nodes[node_index]; + n = &pbvh->nodes[node_index]; /* Update bounding box */ BB_reset(&n->vb); - BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb); - BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb); + BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset].vb); + BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset + 1].vb); n->orig_vb = n->vb; } /* Recursively split the node if it exceeds the leaf_limit */ -static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) +static bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index) { - GSet *bm_faces = bvh->nodes[node_index].bm_faces; + GSet *bm_faces = pbvh->nodes[node_index].bm_faces; const int bm_faces_size = BLI_gset_len(bm_faces); - if (bm_faces_size <= bvh->leaf_limit) { + if (bm_faces_size <= pbvh->leaf_limit) { /* Node limit not exceeded */ return false; } @@ -414,9 +414,9 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) BM_elem_index_set(f, i); /* set_dirty! */ } /* Likely this is already dirty. */ - bvh->bm->elem_index_dirty |= BM_FACE; + pbvh->bm->elem_index_dirty |= BM_FACE; - pbvh_bmesh_node_split(bvh, bbc_array, node_index); + pbvh_bmesh_node_split(pbvh, bbc_array, node_index); MEM_freeN(bbc_array); @@ -426,88 +426,91 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) /**********************************************************************/ #if 0 -static int pbvh_bmesh_node_offset_from_elem(PBVH *bvh, BMElem *ele) +static int pbvh_bmesh_node_offset_from_elem(PBVH *pbvh, BMElem *ele) { switch (ele->head.htype) { case BM_VERT: - return bvh->cd_vert_node_offset; + return pbvh->cd_vert_node_offset; default: BLI_assert(ele->head.htype == BM_FACE); - return bvh->cd_face_node_offset; + return pbvh->cd_face_node_offset; } } -static int pbvh_bmesh_node_index_from_elem(PBVH *bvh, void *key) +static int pbvh_bmesh_node_index_from_elem(PBVH *pbvh, void *key) { - const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(bvh, key); + const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(pbvh, key); const int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset); BLI_assert(node_index != DYNTOPO_NODE_NONE); - BLI_assert(node_index < bvh->totnode); - (void)bvh; + BLI_assert(node_index < pbvh->totnode); + (void)pbvh; return node_index; } -static PBVHNode *pbvh_bmesh_node_from_elem(PBVH *bvh, void *key) +static PBVHNode *pbvh_bmesh_node_from_elem(PBVH *pbvh, void *key) { - return &bvh->nodes[pbvh_bmesh_node_index_from_elem(bvh, key)]; + return &pbvh->nodes[pbvh_bmesh_node_index_from_elem(pbvh, key)]; } /* typecheck */ -# define pbvh_bmesh_node_index_from_elem(bvh, key) \ - (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_index_from_elem(bvh, key)) -# define pbvh_bmesh_node_from_elem(bvh, key) \ - (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_from_elem(bvh, key)) +# define pbvh_bmesh_node_index_from_elem(pbvh, key) \ + (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_index_from_elem(pbvh, key)) +# define pbvh_bmesh_node_from_elem(pbvh, key) \ + (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_from_elem(pbvh, key)) #endif -BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *bvh, const BMVert *key) +BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *pbvh, const BMVert *key) { - const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_vert_node_offset); + const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_vert_node_offset); BLI_assert(node_index != DYNTOPO_NODE_NONE); - BLI_assert(node_index < bvh->totnode); + BLI_assert(node_index < pbvh->totnode); return node_index; } -BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *bvh, const BMFace *key) +BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *pbvh, const BMFace *key) { - const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_face_node_offset); + const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_face_node_offset); BLI_assert(node_index != DYNTOPO_NODE_NONE); - BLI_assert(node_index < bvh->totnode); + BLI_assert(node_index < pbvh->totnode); return node_index; } -BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *bvh, const BMVert *key) +BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *pbvh, const BMVert *key) { - return &bvh->nodes[pbvh_bmesh_node_index_from_vert(bvh, key)]; + return &pbvh->nodes[pbvh_bmesh_node_index_from_vert(pbvh, key)]; } -BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *bvh, const BMFace *key) +BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *pbvh, const BMFace *key) { - return &bvh->nodes[pbvh_bmesh_node_index_from_face(bvh, key)]; + return &pbvh->nodes[pbvh_bmesh_node_index_from_face(pbvh, key)]; } -static BMVert *pbvh_bmesh_vert_create( - PBVH *bvh, int node_index, const float co[3], const float no[3], const int cd_vert_mask_offset) +static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh, + int node_index, + const float co[3], + const float no[3], + const int cd_vert_mask_offset) { - PBVHNode *node = &bvh->nodes[node_index]; + PBVHNode *node = &pbvh->nodes[node_index]; - BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode); + BLI_assert((pbvh->totnode == 1 || node_index) && node_index <= pbvh->totnode); /* avoid initializing customdata because its quite involved */ - BMVert *v = BM_vert_create(bvh->bm, co, NULL, BM_CREATE_SKIP_CD); - CustomData_bmesh_set_default(&bvh->bm->vdata, &v->head.data); + BMVert *v = BM_vert_create(pbvh->bm, co, NULL, BM_CREATE_SKIP_CD); + CustomData_bmesh_set_default(&pbvh->bm->vdata, &v->head.data); /* This value is logged below */ copy_v3_v3(v->no, no); BLI_gset_insert(node->bm_unique_verts, v); - BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, node_index); + BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index); node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; /* Log the new vertex */ - BM_log_vert_added(bvh->bm_log, v, cd_vert_mask_offset); + BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset); return v; } @@ -516,38 +519,38 @@ static BMVert *pbvh_bmesh_vert_create( * \note Callers are responsible for checking if the face exists before adding. */ static BMFace *pbvh_bmesh_face_create( - PBVH *bvh, int node_index, BMVert *v_tri[3], BMEdge *e_tri[3], const BMFace *f_example) + PBVH *pbvh, int node_index, BMVert *v_tri[3], BMEdge *e_tri[3], const BMFace *f_example) { - PBVHNode *node = &bvh->nodes[node_index]; + PBVHNode *node = &pbvh->nodes[node_index]; /* ensure we never add existing face */ BLI_assert(!BM_face_exists(v_tri, 3)); - BMFace *f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP); + BMFace *f = BM_face_create(pbvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP); f->head.hflag = f_example->head.hflag; BLI_gset_insert(node->bm_faces, f); - BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, node_index); + BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index); /* mark node for update */ node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals; node->flag &= ~PBVH_FullyHidden; /* Log the new face */ - BM_log_face_added(bvh->bm_log, f); + BM_log_face_added(pbvh->bm_log, f); return f; } /* Return the number of faces in 'node' that use vertex 'v' */ #if 0 -static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v) +static int pbvh_bmesh_node_vert_use_count(PBVH *pbvh, PBVHNode *node, BMVert *v) { BMFace *f; int count = 0; BM_FACES_OF_VERT_ITER_BEGIN (f, v) { - PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f); + PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f); if (f_node == node) { count++; } @@ -558,10 +561,10 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v) } #endif -#define pbvh_bmesh_node_vert_use_count_is_equal(bvh, node, v, n) \ - (pbvh_bmesh_node_vert_use_count_at_most(bvh, node, v, (n) + 1) == n) +#define pbvh_bmesh_node_vert_use_count_is_equal(pbvh, node, v, n) \ + (pbvh_bmesh_node_vert_use_count_at_most(pbvh, node, v, (n) + 1) == n) -static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh, +static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *pbvh, PBVHNode *node, BMVert *v, const int count_max) @@ -570,7 +573,7 @@ static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh, BMFace *f; BM_FACES_OF_VERT_ITER_BEGIN (f, v) { - PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f); + PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f); if (f_node == node) { count++; if (count == count_max) { @@ -584,13 +587,13 @@ static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh, } /* Return a node that uses vertex 'v' other than its current owner */ -static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v) +static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *pbvh, BMVert *v) { - PBVHNode *current_node = pbvh_bmesh_node_from_vert(bvh, v); + PBVHNode *current_node = pbvh_bmesh_node_from_vert(pbvh, v); BMFace *f; BM_FACES_OF_VERT_ITER_BEGIN (f, v) { - PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f); + PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f); if (f_node != current_node) { return f_node; @@ -601,9 +604,9 @@ static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v) return NULL; } -static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, BMVert *v) +static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner, BMVert *v) { - PBVHNode *current_owner = pbvh_bmesh_node_from_vert(bvh, v); + PBVHNode *current_owner = pbvh_bmesh_node_from_vert(pbvh, v); /* mark node for update */ current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; @@ -613,7 +616,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, B BLI_gset_remove(current_owner->bm_unique_verts, v, NULL); /* Set new ownership */ - BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, new_owner - bvh->nodes); + BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, new_owner - pbvh->nodes); BLI_gset_insert(new_owner->bm_unique_verts, v); BLI_gset_remove(new_owner->bm_other_verts, v, NULL); BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v)); @@ -622,26 +625,26 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, B new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; } -static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) +static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v) { /* never match for first time */ int f_node_index_prev = DYNTOPO_NODE_NONE; - PBVHNode *v_node = pbvh_bmesh_node_from_vert(bvh, v); + PBVHNode *v_node = pbvh_bmesh_node_from_vert(pbvh, v); BLI_gset_remove(v_node->bm_unique_verts, v, NULL); - BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, DYNTOPO_NODE_NONE); + BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE); /* Have to check each neighboring face's node */ BMFace *f; BM_FACES_OF_VERT_ITER_BEGIN (f, v) { - const int f_node_index = pbvh_bmesh_node_index_from_face(bvh, f); + const int f_node_index = pbvh_bmesh_node_index_from_face(pbvh, f); /* faces often share the same node, * quick check to avoid redundant #BLI_gset_remove calls */ if (f_node_index_prev != f_node_index) { f_node_index_prev = f_node_index; - PBVHNode *f_node = &bvh->nodes[f_node_index]; + PBVHNode *f_node = &pbvh->nodes[f_node_index]; f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB; /* Remove current ownership */ @@ -654,9 +657,9 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) BM_FACES_OF_VERT_ITER_END; } -static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) +static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f) { - PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f); + PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f); /* Check if any of this face's vertices need to be removed * from the node */ @@ -664,16 +667,16 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) BMLoop *l_iter = l_first; do { BMVert *v = l_iter->v; - if (pbvh_bmesh_node_vert_use_count_is_equal(bvh, f_node, v, 1)) { + if (pbvh_bmesh_node_vert_use_count_is_equal(pbvh, f_node, v, 1)) { if (BLI_gset_haskey(f_node->bm_unique_verts, v)) { /* Find a different node that uses 'v' */ PBVHNode *new_node; - new_node = pbvh_bmesh_vert_other_node_find(bvh, v); + new_node = pbvh_bmesh_vert_other_node_find(pbvh, v); BLI_assert(new_node || BM_vert_face_count_is_equal(v, 1)); if (new_node) { - pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v); + pbvh_bmesh_vert_ownership_transfer(pbvh, new_node, v); } } else { @@ -685,10 +688,10 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) /* Remove face from node and top level */ BLI_gset_remove(f_node->bm_faces, f, NULL); - BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, DYNTOPO_NODE_NONE); + BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, DYNTOPO_NODE_NONE); /* Log removed face */ - BM_log_face_removed(bvh->bm_log, f); + BM_log_face_removed(pbvh->bm_log, f); /* mark node for update */ f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals; @@ -766,10 +769,10 @@ typedef struct { #ifdef USE_EDGEQUEUE_TAG_VERIFY /* simply check no edges are tagged * (it's a requirement that edges enter and leave a clean tag state) */ -static void pbvh_bmesh_edge_tag_verify(PBVH *bvh) +static void pbvh_bmesh_edge_tag_verify(PBVH *pbvh) { - for (int n = 0; n < bvh->totnode; n++) { - PBVHNode *node = &bvh->nodes[n]; + for (int n = 0; n < pbvh->totnode; n++) { + PBVHNode *node = &pbvh->nodes[n]; if (node->bm_faces) { GSetIterator gs_iter; GSET_ITER (gs_iter, node->bm_faces) { @@ -999,7 +1002,7 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f) * The highest priority (lowest number) is given to the longest edge. */ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, - PBVH *bvh, + PBVH *pbvh, const float center[3], const float view_normal[3], float radius, @@ -1009,9 +1012,9 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, eq_ctx->q->heap = BLI_heapsimple_new(); eq_ctx->q->center = center; eq_ctx->q->radius_squared = radius * radius; - eq_ctx->q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len; + eq_ctx->q->limit_len_squared = pbvh->bm_max_edge_len * pbvh->bm_max_edge_len; #ifdef USE_EDGEQUEUE_EVEN_SUBDIV - eq_ctx->q->limit_len = bvh->bm_max_edge_len; + eq_ctx->q->limit_len = pbvh->bm_max_edge_len; #endif eq_ctx->q->view_normal = view_normal; @@ -1031,11 +1034,11 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, } #ifdef USE_EDGEQUEUE_TAG_VERIFY - pbvh_bmesh_edge_tag_verify(bvh); + pbvh_bmesh_edge_tag_verify(pbvh); #endif - for (int n = 0; n < bvh->totnode; n++) { - PBVHNode *node = &bvh->nodes[n]; + for (int n = 0; n < pbvh->totnode; n++) { + PBVHNode *node = &pbvh->nodes[n]; /* Check leaf nodes marked for topology update */ if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) && @@ -1062,7 +1065,7 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx, * The highest priority (lowest number) is given to the shortest edge. */ static void short_edge_queue_create(EdgeQueueContext *eq_ctx, - PBVH *bvh, + PBVH *pbvh, const float center[3], const float view_normal[3], float radius, @@ -1072,9 +1075,9 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx, eq_ctx->q->heap = BLI_heapsimple_new(); eq_ctx->q->center = center; eq_ctx->q->radius_squared = radius * radius; - eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; + eq_ctx->q->limit_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len; #ifdef USE_EDGEQUEUE_EVEN_SUBDIV - eq_ctx->q->limit_len = bvh->bm_min_edge_len; + eq_ctx->q->limit_len = pbvh->bm_min_edge_len; #endif eq_ctx->q->view_normal = view_normal; @@ -1093,8 +1096,8 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx, eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere; } - for (int n = 0; n < bvh->totnode; n++) { - PBVHNode *node = &bvh->nodes[n]; + for (int n = 0; n < pbvh->totnode; n++) { + PBVHNode *node = &pbvh->nodes[n]; /* Check leaf nodes marked for topology update */ if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) && @@ -1114,7 +1117,7 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx, /*************************** Topology update **************************/ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, - PBVH *bvh, + PBVH *pbvh, BMEdge *e, BLI_Buffer *edge_loops) { @@ -1130,7 +1133,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, int node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset); BMVert *v_new = pbvh_bmesh_vert_create( - bvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset); + pbvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset); /* update paint mask */ if (eq_ctx->cd_vert_mask_offset != -1) { @@ -1163,7 +1166,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, v2 = l_adj->next->v; if (ni != node_index && i == 0) { - pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new); + pbvh_bmesh_vert_ownership_transfer(pbvh, &pbvh->nodes[ni], v_new); } /** @@ -1196,26 +1199,26 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, v_tri[0] = v1; v_tri[1] = v_new; v_tri[2] = v_opp; - bm_edges_from_tri(bvh->bm, v_tri, e_tri); - f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj); + bm_edges_from_tri(pbvh->bm, v_tri, e_tri); + f_new = pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f_adj); long_edge_queue_face_add(eq_ctx, f_new); v_tri[0] = v_new; v_tri[1] = v2; /* v_tri[2] = v_opp; */ /* unchanged */ - e_tri[0] = BM_edge_create(bvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE); + e_tri[0] = BM_edge_create(pbvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE); e_tri[2] = e_tri[1]; /* switched */ - e_tri[1] = BM_edge_create(bvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE); - f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj); + e_tri[1] = BM_edge_create(pbvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE); + f_new = pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f_adj); long_edge_queue_face_add(eq_ctx, f_new); /* Delete original */ - pbvh_bmesh_face_remove(bvh, f_adj); - BM_face_kill(bvh->bm, f_adj); + pbvh_bmesh_face_remove(pbvh, f_adj); + BM_face_kill(pbvh->bm, f_adj); /* Ensure new vertex is in the node */ - if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new)) { - BLI_gset_add(bvh->nodes[ni].bm_other_verts, v_new); + if (!BLI_gset_haskey(pbvh->nodes[ni].bm_unique_verts, v_new)) { + BLI_gset_add(pbvh->nodes[ni].bm_other_verts, v_new); } if (BM_vert_edge_count_is_over(v_opp, 8)) { @@ -1228,11 +1231,11 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, } } - BM_edge_kill(bvh->bm, e); + BM_edge_kill(pbvh->bm, e); } static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, - PBVH *bvh, + PBVH *pbvh, BLI_Buffer *edge_loops) { bool any_subdivided = false; @@ -1274,17 +1277,17 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, any_subdivided = true; - pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops); + pbvh_bmesh_split_edge(eq_ctx, pbvh, e, edge_loops); } #ifdef USE_EDGEQUEUE_TAG_VERIFY - pbvh_bmesh_edge_tag_verify(bvh); + pbvh_bmesh_edge_tag_verify(pbvh); #endif return any_subdivided; } -static void pbvh_bmesh_collapse_edge(PBVH *bvh, +static void pbvh_bmesh_collapse_edge(PBVH *pbvh, BMEdge *e, BMVert *v1, BMVert *v2, @@ -1306,20 +1309,20 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, } /* Remove the merge vertex from the PBVH */ - pbvh_bmesh_vert_remove(bvh, v_del); + pbvh_bmesh_vert_remove(pbvh, v_del); /* Remove all faces adjacent to the edge */ BMLoop *l_adj; while ((l_adj = e->l)) { BMFace *f_adj = l_adj->f; - pbvh_bmesh_face_remove(bvh, f_adj); - BM_face_kill(bvh->bm, f_adj); + pbvh_bmesh_face_remove(pbvh, f_adj); + BM_face_kill(pbvh->bm, f_adj); } /* Kill the edge */ BLI_assert(BM_edge_is_wire(e)); - BM_edge_kill(bvh->bm, e); + BM_edge_kill(pbvh->bm, e); /* For all remaining faces of v_del, create a new face that is the * same except it uses v_conn instead of v_del */ @@ -1364,10 +1367,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BLI_assert(!BM_face_exists(v_tri, 3)); BMEdge *e_tri[3]; - PBVHNode *n = pbvh_bmesh_node_from_face(bvh, f); - int ni = n - bvh->nodes; - bm_edges_from_tri(bvh->bm, v_tri, e_tri); - pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f); + PBVHNode *n = pbvh_bmesh_node_from_face(pbvh, f); + int ni = n - pbvh->nodes; + bm_edges_from_tri(pbvh->bm, v_tri, e_tri); + pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f); /* Ensure that v_conn is in the new face's node */ if (!BLI_gset_haskey(n->bm_unique_verts, v_conn)) { @@ -1398,14 +1401,14 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, e_tri[2] = l_iter->e; /* Remove the face */ - pbvh_bmesh_face_remove(bvh, f_del); - BM_face_kill(bvh->bm, f_del); + pbvh_bmesh_face_remove(pbvh, f_del); + BM_face_kill(pbvh->bm, f_del); /* Check if any of the face's edges are now unused by any * face, if so delete them */ for (int j = 0; j < 3; j++) { if (BM_edge_is_wire(e_tri[j])) { - BM_edge_kill(bvh->bm, e_tri[j]); + BM_edge_kill(pbvh->bm, e_tri[j]); } } @@ -1413,15 +1416,15 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, * remove them from the PBVH */ for (int j = 0; j < 3; j++) { if ((v_tri[j] != v_del) && (v_tri[j]->e == NULL)) { - pbvh_bmesh_vert_remove(bvh, v_tri[j]); + pbvh_bmesh_vert_remove(pbvh, v_tri[j]); - BM_log_vert_removed(bvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset); + BM_log_vert_removed(pbvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset); if (v_tri[j] == v_conn) { v_conn = NULL; } BLI_ghash_insert(deleted_verts, v_tri[j], NULL); - BM_vert_kill(bvh->bm, v_tri[j]); + BM_vert_kill(pbvh->bm, v_tri[j]); } } } @@ -1429,7 +1432,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, /* Move v_conn to the midpoint of v_conn and v_del (if v_conn still exists, it * may have been deleted above) */ if (v_conn != NULL) { - BM_log_vert_before_modified(bvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset); + BM_log_vert_before_modified(pbvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset); mid_v3_v3v3(v_conn->co, v_conn->co, v_del->co); add_v3_v3(v_conn->no, v_del->no); normalize_v3(v_conn->no); @@ -1437,7 +1440,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, /* update boundboxes attached to the connected vertex * note that we can often get-away without this but causes T48779 */ BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) { - PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, l->f); + PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, l->f); f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateBB; } BM_LOOPS_OF_VERT_ITER_END; @@ -1445,17 +1448,17 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, /* Delete v_del */ BLI_assert(!BM_vert_face_check(v_del)); - BM_log_vert_removed(bvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset); + BM_log_vert_removed(pbvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset); /* v_conn == NULL is OK */ BLI_ghash_insert(deleted_verts, v_del, v_conn); - BM_vert_kill(bvh->bm, v_del); + BM_vert_kill(pbvh->bm, v_del); } static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, - PBVH *bvh, + PBVH *pbvh, BLI_Buffer *deleted_faces) { - const float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; + const float min_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len; bool any_collapsed = false; /* deleted verts point to vertices they were merged into, or NULL when removed. */ GHash *deleted_verts = BLI_ghash_ptr_new("deleted_verts"); @@ -1496,7 +1499,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, any_collapsed = true; - pbvh_bmesh_collapse_edge(bvh, e, v1, v2, deleted_verts, deleted_faces, eq_ctx); + pbvh_bmesh_collapse_edge(pbvh, e, v1, v2, deleted_verts, deleted_faces, eq_ctx); } BLI_ghash_free(deleted_verts, NULL, NULL); @@ -1691,11 +1694,11 @@ struct FastNodeBuildInfo { * to a sub part of the arrays. */ static void pbvh_bmesh_node_limit_ensure_fast( - PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, MemArena *arena) + PBVH *pbvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, MemArena *arena) { struct FastNodeBuildInfo *child1, *child2; - if (node->totface <= bvh->leaf_limit) { + if (node->totface <= pbvh->leaf_limit) { return; } @@ -1782,38 +1785,38 @@ static void pbvh_bmesh_node_limit_ensure_fast( child2->start = node->start + num_child1; child1->child1 = child1->child2 = child2->child1 = child2->child2 = NULL; - pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child1, arena); - pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child2, arena); + pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, child1, arena); + pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, child2, arena); } static void pbvh_bmesh_create_nodes_fast_recursive( - PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, int node_index) + PBVH *pbvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, int node_index) { - PBVHNode *n = bvh->nodes + node_index; + PBVHNode *n = pbvh->nodes + node_index; /* two cases, node does not have children or does have children */ if (node->child1) { - int children_offset = bvh->totnode; + int children_offset = pbvh->totnode; n->children_offset = children_offset; - pbvh_grow_nodes(bvh, bvh->totnode + 2); + pbvh_grow_nodes(pbvh, pbvh->totnode + 2); pbvh_bmesh_create_nodes_fast_recursive( - bvh, nodeinfo, bbc_array, node->child1, children_offset); + pbvh, nodeinfo, bbc_array, node->child1, children_offset); pbvh_bmesh_create_nodes_fast_recursive( - bvh, nodeinfo, bbc_array, node->child2, children_offset + 1); + pbvh, nodeinfo, bbc_array, node->child2, children_offset + 1); - n = &bvh->nodes[node_index]; + n = &pbvh->nodes[node_index]; /* Update bounding box */ BB_reset(&n->vb); - BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb); - BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb); + BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset].vb); + BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset + 1].vb); n->orig_vb = n->vb; } else { /* node does not have children so it's a leaf node, populate with faces and tag accordingly * this is an expensive part but it's not so easily thread-able due to vertex node indices */ - const int cd_vert_node_offset = bvh->cd_vert_node_offset; - const int cd_face_node_offset = bvh->cd_face_node_offset; + const int cd_vert_node_offset = pbvh->cd_vert_node_offset; + const int cd_face_node_offset = pbvh->cd_face_node_offset; bool has_visible = false; @@ -1876,27 +1879,27 @@ static void pbvh_bmesh_create_nodes_fast_recursive( /***************************** Public API *****************************/ /* Build a PBVH from a BMesh */ -void BKE_pbvh_build_bmesh(PBVH *bvh, +void BKE_pbvh_build_bmesh(PBVH *pbvh, BMesh *bm, bool smooth_shading, BMLog *log, const int cd_vert_node_offset, const int cd_face_node_offset) { - bvh->cd_vert_node_offset = cd_vert_node_offset; - bvh->cd_face_node_offset = cd_face_node_offset; - bvh->bm = bm; + pbvh->cd_vert_node_offset = cd_vert_node_offset; + pbvh->cd_face_node_offset = cd_face_node_offset; + pbvh->bm = bm; - BKE_pbvh_bmesh_detail_size_set(bvh, 0.75); + BKE_pbvh_bmesh_detail_size_set(pbvh, 0.75); - bvh->type = PBVH_BMESH; - bvh->bm_log = log; + pbvh->type = PBVH_BMESH; + pbvh->bm_log = log; /* TODO: choose leaf limit better */ - bvh->leaf_limit = 100; + pbvh->leaf_limit = 100; if (smooth_shading) { - bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING; + pbvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING; } /* bounding box array of all faces, no need to recalculate every time */ @@ -1936,17 +1939,17 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, rootnode.totface = bm->totface; /* start recursion, assign faces to nodes accordingly */ - pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, &rootnode, arena); + pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, &rootnode, arena); /* We now have all faces assigned to a node, * next we need to assign those to the gsets of the nodes. */ /* Start with all faces in the root node */ - bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode"); - bvh->totnode = 1; + pbvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode"); + pbvh->totnode = 1; /* take root node and visit and populate children recursively */ - pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, &rootnode, 0); + pbvh_bmesh_create_nodes_fast_recursive(pbvh, nodeinfo, bbc_array, &rootnode, 0); BLI_memarena_free(arena); MEM_freeN(bbc_array); @@ -1954,7 +1957,7 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, } /* Collapse short edges, subdivide long edges */ -bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, +bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh, PBVHTopologyUpdateMode mode, const float center[3], const float view_normal[3], @@ -1965,9 +1968,9 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, /* 2 is enough for edge faces - manifold edge */ BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2); BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); - const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK); - const int cd_vert_node_offset = bvh->cd_vert_node_offset; - const int cd_face_node_offset = bvh->cd_face_node_offset; + const int cd_vert_mask_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK); + const int cd_vert_node_offset = pbvh->cd_vert_node_offset; + const int cd_face_node_offset = pbvh->cd_face_node_offset; bool modified = false; @@ -1981,15 +1984,15 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, EdgeQueueContext eq_ctx = { &q, queue_pool, - bvh->bm, + pbvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset, }; short_edge_queue_create( - &eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected); - modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &deleted_faces); + &eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected); + modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, pbvh, &deleted_faces); BLI_heapsimple_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); } @@ -2000,22 +2003,22 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, EdgeQueueContext eq_ctx = { &q, queue_pool, - bvh->bm, + pbvh->bm, cd_vert_mask_offset, cd_vert_node_offset, cd_face_node_offset, }; long_edge_queue_create( - &eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected); - modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops); + &eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected); + modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, pbvh, &edge_loops); BLI_heapsimple_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); } /* Unmark nodes */ - for (int n = 0; n < bvh->totnode; n++) { - PBVHNode *node = &bvh->nodes[n]; + for (int n = 0; n < pbvh->totnode; n++) { + PBVHNode *node = &pbvh->nodes[n]; if (node->flag & PBVH_Leaf && node->flag & PBVH_UpdateTopology) { node->flag &= ~PBVH_UpdateTopology; @@ -2025,7 +2028,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh, BLI_buffer_free(&deleted_faces); #ifdef USE_VERIFY - pbvh_bmesh_verify(bvh); + pbvh_bmesh_verify(pbvh); #endif return modified; @@ -2092,25 +2095,25 @@ void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node) node->bm_tot_ortri = i; } -void BKE_pbvh_bmesh_after_stroke(PBVH *bvh) +void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh) { - for (int i = 0; i < bvh->totnode; i++) { - PBVHNode *n = &bvh->nodes[i]; + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *n = &pbvh->nodes[i]; if (n->flag & PBVH_Leaf) { /* Free orco/ortri data */ pbvh_bmesh_node_drop_orig(n); /* Recursively split nodes that have gotten too many * elements */ - pbvh_bmesh_node_limit_ensure(bvh, i); + pbvh_bmesh_node_limit_ensure(pbvh, i); } } } -void BKE_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size) +void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size) { - bvh->bm_max_edge_len = detail_size; - bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4f; + pbvh->bm_max_edge_len = detail_size; + pbvh->bm_min_edge_len = pbvh->bm_max_edge_len * 0.4f; } void BKE_pbvh_node_mark_topology_update(PBVHNode *node) @@ -2137,25 +2140,25 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node) #if 0 -static void pbvh_bmesh_print(PBVH *bvh) +static void pbvh_bmesh_print(PBVH *pbvh) { - fprintf(stderr, "\npbvh=%p\n", bvh); + fprintf(stderr, "\npbvh=%p\n", pbvh); fprintf(stderr, "bm_face_to_node:\n"); BMIter iter; BMFace *f; - BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) { - fprintf(stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(bvh, f)); + BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) { + fprintf(stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(pbvh, f)); } fprintf(stderr, "bm_vert_to_node:\n"); BMVert *v; - BM_ITER_MESH (v, &iter, bvh->bm, BM_FACES_OF_MESH) { - fprintf(stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(bvh, v)); + BM_ITER_MESH (v, &iter, pbvh->bm, BM_FACES_OF_MESH) { + fprintf(stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(pbvh, v)); } - for (int n = 0; n < bvh->totnode; n++) { - PBVHNode *node = &bvh->nodes[n]; + for (int n = 0; n < pbvh->totnode; n++) { + PBVHNode *node = &pbvh->nodes[n]; if (!(node->flag & PBVH_Leaf)) { continue; } @@ -2186,25 +2189,25 @@ static void print_flag_factors(int flag) #ifdef USE_VERIFY -static void pbvh_bmesh_verify(PBVH *bvh) +static void pbvh_bmesh_verify(PBVH *pbvh) { /* build list of faces & verts to lookup */ - GSet *faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface); + GSet *faces_all = BLI_gset_ptr_new_ex(__func__, pbvh->bm->totface); BMIter iter; { BMFace *f; - BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) { - BLI_assert(BM_ELEM_CD_GET_INT(f, bvh->cd_face_node_offset) != DYNTOPO_NODE_NONE); + BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) { + BLI_assert(BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset) != DYNTOPO_NODE_NONE); BLI_gset_insert(faces_all, f); } } - GSet *verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert); + GSet *verts_all = BLI_gset_ptr_new_ex(__func__, pbvh->bm->totvert); { BMVert *v; - BM_ITER_MESH (v, &iter, bvh->bm, BM_VERTS_OF_MESH) { - if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) { + BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) { + if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) { BLI_gset_insert(verts_all, v); } } @@ -2213,8 +2216,8 @@ static void pbvh_bmesh_verify(PBVH *bvh) /* Check vert/face counts */ { int totface = 0, totvert = 0; - for (int i = 0; i < bvh->totnode; i++) { - PBVHNode *n = &bvh->nodes[i]; + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *n = &pbvh->nodes[i]; totface += n->bm_faces ? BLI_gset_len(n->bm_faces) : 0; totvert += n->bm_unique_verts ? BLI_gset_len(n->bm_unique_verts) : 0; } @@ -2225,10 +2228,10 @@ static void pbvh_bmesh_verify(PBVH *bvh) { BMFace *f; - BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) { + BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) { BMIter bm_iter; BMVert *v; - PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f); + PBVHNode *n = pbvh_bmesh_node_lookup(pbvh, f); /* Check that the face's node is a leaf */ BLI_assert(n->flag & PBVH_Leaf); @@ -2244,7 +2247,7 @@ static void pbvh_bmesh_verify(PBVH *bvh) BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v) ^ BLI_gset_haskey(n->bm_other_verts, v)); /* Check that the vertex has a node owner */ - nv = pbvh_bmesh_node_lookup(bvh, v); + nv = pbvh_bmesh_node_lookup(pbvh, v); /* Check that the vertex's node knows it owns the vert */ BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v)); @@ -2258,13 +2261,13 @@ static void pbvh_bmesh_verify(PBVH *bvh) /* Check verts */ { BMVert *v; - BM_ITER_MESH (v, &iter, bvh->bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) { /* vertex isn't tracked */ - if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) { + if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) { continue; } - PBVHNode *n = pbvh_bmesh_node_lookup(bvh, v); + PBVHNode *n = pbvh_bmesh_node_lookup(pbvh, v); /* Check that the vert's node is a leaf */ BLI_assert(n->flag & PBVH_Leaf); @@ -2281,7 +2284,7 @@ static void pbvh_bmesh_verify(PBVH *bvh) BMIter bm_iter; BMFace *f = NULL; BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { - if (pbvh_bmesh_node_lookup(bvh, f) == n) { + if (pbvh_bmesh_node_lookup(pbvh, f) == n) { found = true; break; } @@ -2291,8 +2294,8 @@ static void pbvh_bmesh_verify(PBVH *bvh) # if 1 /* total freak stuff, check if node exists somewhere else */ /* Slow */ - for (int i = 0; i < bvh->totnode; i++) { - PBVHNode *n_other = &bvh->nodes[i]; + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *n_other = &pbvh->nodes[i]; if ((n != n_other) && (n_other->bm_unique_verts)) { BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v)); } @@ -2304,10 +2307,10 @@ static void pbvh_bmesh_verify(PBVH *bvh) # if 0 /* check that every vert belongs somewhere */ /* Slow */ - BM_ITER_MESH (vi, &iter, bvh->bm, BM_VERTS_OF_MESH) { + BM_ITER_MESH (vi, &iter, pbvh->bm, BM_VERTS_OF_MESH) { bool has_unique = false; - for (int i = 0; i < bvh->totnode; i++) { - PBVHNode *n = &bvh->nodes[i]; + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *n = &pbvh->nodes[i]; if ((n->bm_unique_verts != NULL) && BLI_gset_haskey(n->bm_unique_verts, vi)) { has_unique = true; } @@ -2317,25 +2320,25 @@ static void pbvh_bmesh_verify(PBVH *bvh) } /* if totvert differs from number of verts inside the hash. hash-totvert is checked above */ - BLI_assert(vert_count == bvh->bm->totvert); + BLI_assert(vert_count == pbvh->bm->totvert); # endif /* Check that node elements are recorded in the top level */ - for (int i = 0; i < bvh->totnode; i++) { - PBVHNode *n = &bvh->nodes[i]; + for (int i = 0; i < pbvh->totnode; i++) { + PBVHNode *n = &pbvh->nodes[i]; if (n->flag & PBVH_Leaf) { GSetIterator gs_iter; GSET_ITER (gs_iter, n->bm_faces) { BMFace *f = BLI_gsetIterator_getKey(&gs_iter); - PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, f); + PBVHNode *n_other = pbvh_bmesh_node_lookup(pbvh, f); BLI_assert(n == n_other); BLI_assert(BLI_gset_haskey(faces_all, f)); } GSET_ITER (gs_iter, n->bm_unique_verts) { BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, v); + PBVHNode *n_other = pbvh_bmesh_node_lookup(pbvh, v); BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v)); BLI_assert(n == n_other); BLI_assert(BLI_gset_haskey(verts_all, v)); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 7d60d21a496..bb7ec0adc19 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -672,7 +672,6 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag) } BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag); - ts->imapaint.paintcursor = NULL; ts->particle.paintcursor = NULL; ts->particle.scene = NULL; ts->particle.object = NULL; diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c index dc75e2b9098..30a371b5b28 100644 --- a/source/blender/blenkernel/intern/seqprefetch.c +++ b/source/blender/blenkernel/intern/seqprefetch.c @@ -435,11 +435,8 @@ static void *seq_prefetch_frames(void *job) seq_prefetch_update_depsgraph(pfjob); AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id); - BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id, - adt, - seq_prefetch_cfra(pfjob), - ADT_RECALC_ALL, - false); + BKE_animsys_evaluate_animdata( + &pfjob->context_cpy.scene->id, adt, seq_prefetch_cfra(pfjob), ADT_RECALC_ALL, false); /* This is quite hacky solution: * We need cross-reference original scene with copy for cache. diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index aef274f7d91..4892e8d6ede 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -503,10 +503,8 @@ static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl) sl->equirect_radiance_gputexture = GPU_texture_create_2d( ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL); GPUTexture *tex = sl->equirect_radiance_gputexture; - GPU_texture_bind(tex, 0); GPU_texture_filter_mode(tex, true); GPU_texture_wrap_mode(tex, true, true); - GPU_texture_unbind(tex); } sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE; } @@ -567,10 +565,8 @@ static void studiolight_create_equirect_irradiance_gputexture(StudioLight *sl) sl->equirect_irradiance_gputexture = GPU_texture_create_2d( ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL); GPUTexture *tex = sl->equirect_irradiance_gputexture; - GPU_texture_bind(tex, 0); GPU_texture_filter_mode(tex, true); GPU_texture_wrap_mode(tex, true, true); - GPU_texture_unbind(tex); } sl->flag |= STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE; } diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index 3f44c13ba19..a8136dd7932 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -713,6 +713,113 @@ static bool ch_is_op(char op) } } +/** + * Helper function for #unit_distribute_negatives to find the next negative to distribute. + * + * \note This unecessarily skips the next space if it comes right after the "-" + * just to make a more predictable output. + */ +static char *find_next_negative(const char *str, const char *remaining_str) +{ + char *str_found = strstr(remaining_str, "-"); + + if (str_found == NULL) { + return NULL; + } + + /* Don't use the "-" from scientific notation, but make sure we can look backwards first. */ + if ((str_found != str) && ELEM(*(str_found - 1), 'e', 'E')) { + return find_next_negative(str, str_found + 1); + } + + if (*(str_found + 1) == ' ') { + str_found++; + } + + return str_found + 1; +} + +/** + * Helper function for #unit_distribute_negatives to find the next operation, including "-". + * + * \note This unecessarily skips the space before the operation character + * just to make a more predictable output. + */ +static char *find_next_op(const char *str, char *remaining_str, int len_max) +{ + int i; + bool scientific_notation = false; + for (i = 0; i < len_max; i++) { + if (remaining_str[i] == '\0') { + return remaining_str + i; + } + + if (ch_is_op(remaining_str[i])) { + if (scientific_notation) { + scientific_notation = false; + continue; + } + + /* Make sure we don't look backwards before the start of the string. */ + if (remaining_str != str && i != 0) { + /* Check for scientific notation. */ + if (remaining_str[i - 1] == 'e' || remaining_str[i - 1] == 'E') { + scientific_notation = true; + continue; + } + + /* Return position before a space character. */ + if (remaining_str[i - 1] == ' ') { + i--; + } + } + + return remaining_str + i; + } + } + BLI_assert(!"String should be NULL terminated"); + return remaining_str + i; +} + +/** + * Put parentheses around blocks of values after negative signs to get rid of an implied "+" + * between numbers without an operation between them. For example: + * + * "-1m50cm + 1 - 2m50cm" -> "-(1m50cm) + 1 - (2m50cm)" + */ +static bool unit_distribute_negatives(char *str, const int len_max) +{ + bool changed = false; + + char *remaining_str = str; + int remaining_str_len = len_max; + while ((remaining_str = find_next_negative(str, remaining_str)) != NULL) { + /* Exit early in the unlikely situation that we've run out of length to add the parentheses. */ + remaining_str_len = len_max - (int)(remaining_str - str); + if (remaining_str_len <= 2) { + return changed; + } + + changed = true; + + /* Add '(', shift the following characters to the right to make space. */ + memmove(remaining_str + 1, remaining_str, remaining_str_len - 2); + *remaining_str = '('; + + /* Add the ')' before the next operation or at the end. */ + remaining_str = find_next_op(str, remaining_str + 1, remaining_str_len); + remaining_str_len = len_max - (int)(remaining_str - str); + memmove(remaining_str + 1, remaining_str, remaining_str_len - 2); + *remaining_str = ')'; + + /* Only move forward by 1 even though we added two characters. Minus signs need to be able to + * apply to the next block of values too. */ + remaining_str += 1; + } + + return changed; +} + static int unit_scale_str(char *str, int len_max, char *str_tmp, @@ -896,6 +1003,10 @@ bool bUnit_ReplaceString( char str_tmp[TEMP_STR_SIZE]; bool changed = false; + /* Fix cases like "-1m50cm" which would evaluate to -0.5m without this. */ + changed |= unit_distribute_negatives(str, len_max); + printf("%s\n", str); + /* Try to find a default unit from current or previous string. */ default_unit = unit_detect_from_str(usys, str, str_prev); diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h index f280b8f3b9c..175aa4ab9d0 100644 --- a/source/blender/blenloader/BLO_undofile.h +++ b/source/blender/blenloader/BLO_undofile.h @@ -26,6 +26,7 @@ */ struct Scene; +struct GHash; typedef struct { void *next, *prev; @@ -38,6 +39,9 @@ typedef struct { * detect unchanged IDs). * Defined when writing the next step (i.e. last undo step has those always false). */ bool is_identical_future; + /** Session uuid of the ID being curently written (MAIN_ID_SESSION_UUID_UNSET when not writing + * ID-related data). Used to find matching chunks in previous memundo step. */ + uint id_session_uuid; } MemFileChunk; typedef struct MemFile { @@ -45,6 +49,17 @@ typedef struct MemFile { size_t size; } MemFile; +typedef struct MemFileWriteData { + MemFile *written_memfile; + MemFile *reference_memfile; + + uint current_id_session_uuid; + MemFileChunk *reference_current_chunk; + + /** Maps an ID session uuid to its first reference MemFileChunk, if existing. */ + struct GHash *id_session_uuid_mapping; +} MemFileWriteData; + typedef struct MemFileUndoData { char filename[1024]; /* FILE_MAX */ MemFile memfile; @@ -52,10 +67,13 @@ typedef struct MemFileUndoData { } MemFileUndoData; /* actually only used writefile.c */ -extern void memfile_chunk_add(MemFile *memfile, - const char *buf, - unsigned int size, - MemFileChunk **compchunk_step); + +void BLO_memfile_write_init(MemFileWriteData *mem_data, + MemFile *written_memfile, + MemFile *reference_memfile); +void BLO_memfile_write_finalize(MemFileWriteData *mem_data); + +void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, unsigned int size); /* exports */ extern void BLO_memfile_free(MemFile *memfile); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index db63091ce36..c9027eae296 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6984,7 +6984,6 @@ static void direct_link_scene(FileData *fd, Scene *sce) direct_link_paint(fd, sce, &sce->toolsettings->imapaint.paint); - sce->toolsettings->imapaint.paintcursor = NULL; sce->toolsettings->particle.paintcursor = NULL; sce->toolsettings->particle.scene = NULL; sce->toolsettings->particle.object = NULL; diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c index c7057883f88..28b37c4a737 100644 --- a/source/blender/blenloader/intern/undofile.c +++ b/source/blender/blenloader/intern/undofile.c @@ -41,10 +41,12 @@ #include "DNA_listBase.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLO_readfile.h" #include "BLO_undofile.h" +#include "BKE_lib_id.h" #include "BKE_main.h" /* keep last */ @@ -100,8 +102,52 @@ void BLO_memfile_clear_future(MemFile *memfile) } } -void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChunk **compchunk_step) +void BLO_memfile_write_init(MemFileWriteData *mem_data, + MemFile *written_memfile, + MemFile *reference_memfile) { + mem_data->written_memfile = written_memfile; + mem_data->reference_memfile = reference_memfile; + mem_data->reference_current_chunk = reference_memfile ? reference_memfile->chunks.first : NULL; + + /* If we have a reference memfile, we generate a mapping between the session_uuid's of the IDs + * stored in that previous undo step, and its first matching memchunk. + * This will allow us to easily find the existing undo memory storage of IDs even when some + * re-ordering in current Main data-base broke the order matching with the memchunks from + * previous step. */ + if (reference_memfile != NULL) { + mem_data->id_session_uuid_mapping = BLI_ghash_new( + BLI_ghashutil_inthash_p_simple, BLI_ghashutil_intcmp, __func__); + uint current_session_uuid = MAIN_ID_SESSION_UUID_UNSET; + LISTBASE_FOREACH (MemFileChunk *, mem_chunk, &reference_memfile->chunks) { + if (!ELEM(mem_chunk->id_session_uuid, MAIN_ID_SESSION_UUID_UNSET, current_session_uuid)) { + current_session_uuid = mem_chunk->id_session_uuid; + void **entry; + if (!BLI_ghash_ensure_p(mem_data->id_session_uuid_mapping, + POINTER_FROM_UINT(current_session_uuid), + &entry)) { + *entry = mem_chunk; + } + else { + BLI_assert(0); + } + } + } + } +} + +void BLO_memfile_write_finalize(MemFileWriteData *mem_data) +{ + if (mem_data->id_session_uuid_mapping != NULL) { + BLI_ghash_free(mem_data->id_session_uuid_mapping, NULL, NULL); + } +} + +void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, uint size) +{ + MemFile *memfile = mem_data->written_memfile; + MemFileChunk **compchunk_step = &mem_data->reference_current_chunk; + MemFileChunk *curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk"); curchunk->size = size; curchunk->buf = NULL; @@ -110,6 +156,7 @@ void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChun * perform an undo push may make changes after the last undo push that * will then not be undo. Though it's not entirely clear that is wrong behavior. */ curchunk->is_identical_future = true; + curchunk->id_session_uuid = mem_data->current_id_session_uuid; BLI_addtail(&memfile->chunks, curchunk); /* we compare compchunk with buf */ diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 6574c983b09..1aa569d8336 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -249,7 +249,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) LISTBASE_FOREACH (Object *, ob, &bmain->objects) { LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { if (md->type == eModifierType_WeightVGEdit) { - md->flag &= ~MOD_WVG_EDIT_WEIGHTS_NORMALIZE; + ((WeightVGEditModifierData *)md)->edit_flags &= ~MOD_WVG_EDIT_WEIGHTS_NORMALIZE; } } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 57c9ca16693..91d89254c90 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -465,6 +465,9 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) /* Reset all grease pencil brushes. */ Scene *scene = bmain->scenes.first; BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings, true); + BKE_brush_gpencil_sculpt_presets(bmain, scene->toolsettings, true); + BKE_brush_gpencil_vertex_presets(bmain, scene->toolsettings, true); + BKE_brush_gpencil_weight_presets(bmain, scene->toolsettings, true); /* Ensure new Paint modes. */ BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index c7d9fbf7268..bc36497dd9f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -164,6 +164,7 @@ #include "BKE_gpencil_modifier.h" #include "BKE_idtype.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_main.h" #include "BKE_modifier.h" @@ -328,12 +329,7 @@ typedef struct { bool error; /** #MemFile writing (used for undo). */ - struct { - MemFile *current; - MemFile *compare; - /** Use to de-duplicate chunks when writing. */ - MemFileChunk *compare_chunk; - } mem; + MemFileWriteData mem; /** When true, write to #WriteData.current, could also call 'is_undo'. */ bool use_memfile; @@ -372,7 +368,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen) /* memory based save */ if (wd->use_memfile) { - memfile_chunk_add(wd->mem.current, mem, memlen, &wd->mem.compare_chunk); + BLO_memfile_chunk_add(&wd->mem, mem, memlen); } else { if (wd->ww->write(wd->ww, mem, memlen) != memlen) { @@ -473,9 +469,7 @@ static WriteData *mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *curren WriteData *wd = writedata_new(ww); if (current != NULL) { - wd->mem.current = current; - wd->mem.compare = compare; - wd->mem.compare_chunk = compare ? compare->chunks.first : NULL; + BLO_memfile_write_init(&wd->mem, current, compare); wd->use_memfile = true; } @@ -495,12 +489,58 @@ static bool mywrite_end(WriteData *wd) wd->buf_used_len = 0; } + if (wd->use_memfile) { + BLO_memfile_write_finalize(&wd->mem); + } + const bool err = wd->error; writedata_free(wd); return err; } +/** + * Start writing of data related to a single ID. + * + * Only does something when storing an undo step. + */ +static void mywrite_id_begin(WriteData *wd, ID *id) +{ + if (wd->use_memfile) { + wd->mem.current_id_session_uuid = id->session_uuid; + + /* If current next memchunk does not match the ID we are about to write, try to find the + * correct memchunk in the mapping using ID's session_uuid. */ + if (wd->mem.id_session_uuid_mapping != NULL && + (wd->mem.reference_current_chunk == NULL || + wd->mem.reference_current_chunk->id_session_uuid != id->session_uuid)) { + void *ref = BLI_ghash_lookup(wd->mem.id_session_uuid_mapping, + POINTER_FROM_UINT(id->session_uuid)); + if (ref != NULL) { + wd->mem.reference_current_chunk = ref; + } + /* Else, no existing memchunk found, i.e. this is supposed to be a new ID. */ + } + /* Otherwise, we try with the current memchunk in any case, whether it is matching current + * ID's session_uuid or not. */ + } +} + +/** + * Start writing of data related to a single ID. + * + * Only does something when storing an undo step. + */ +static void mywrite_id_end(WriteData *wd, ID *UNUSED(id)) +{ + if (wd->use_memfile) { + /* Very important to do it after every ID write now, otherwise we cannot know whether a + * specific ID changed or not. */ + mywrite_flush(wd); + wd->mem.current_id_session_uuid = MAIN_ID_SESSION_UUID_UNSET; + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -4149,6 +4189,8 @@ static bool write_file_handle(Main *mainvar, } } + mywrite_id_begin(wd, id); + memcpy(id_buffer, id, idtype_struct_size); ((ID *)id_buffer)->tag = 0; @@ -4290,11 +4332,7 @@ static bool write_file_handle(Main *mainvar, BKE_lib_override_library_operations_store_end(override_storage, id); } - if (wd->use_memfile) { - /* Very important to do it after every ID write now, otherwise we cannot know whether a - * specific ID changed or not. */ - mywrite_flush(wd); - } + mywrite_id_end(wd, id); } if (id_buffer != id_buffer_static) { diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 1bf419f4461..177599656b6 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -1021,7 +1021,7 @@ void BM_select_history_validate(BMesh *bm) bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese) { BMEditSelection *ese_last = bm->selected.last; - BMFace *efa = BM_mesh_active_face_get(bm, false, false); + BMFace *efa = BM_mesh_active_face_get(bm, false, true); ese->next = ese->prev = NULL; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index c98aab51654..f5a131a1731 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1500,7 +1500,10 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) } } if (property_entry_key.prop != nullptr && RNA_property_is_idprop(property_entry_key.prop)) { - RNAPathKey property_exit_key(id, rna_path, RNAPointerSource::EXIT); + RNAPathKey property_exit_key(property_entry_key.id, + property_entry_key.ptr, + property_entry_key.prop, + RNAPointerSource::EXIT); OperationKey parameters_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL); add_relation(property_exit_key, parameters_key, "Driven Property -> Properties"); } @@ -2889,6 +2892,9 @@ void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node) DriverGroupMap driver_groups; LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { + if (fcu->rna_path == nullptr) { + continue; + } // Get the RNA path except the part after the last dot. char *last_dot = strrchr(fcu->rna_path, '.'); string rna_prefix; @@ -2939,7 +2945,7 @@ void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node) } } } -} +} // namespace DEG /* **** ID traversal callbacks functions **** */ diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index d9f7a3acae0..aeecb452217 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -34,6 +34,7 @@ set(INC ../imbuf ../makesdna ../makesrna + ../nodes ../render/extern/include ../render/intern/include ../windowmanager @@ -317,8 +318,8 @@ data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC) data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC) data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC) -data_to_c_simple(engines/basic/shaders/conservative_depth_vert.glsl SRC) -data_to_c_simple(engines/basic/shaders/conservative_depth_frag.glsl SRC) +data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC) +data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC) if(WITH_LANPR) data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_preview_geom.glsl SRC) diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 6658fea7825..bbc3c407f14 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -37,8 +37,8 @@ #define BASIC_ENGINE "BLENDER_BASIC" -extern char datatoc_conservative_depth_frag_glsl[]; -extern char datatoc_conservative_depth_vert_glsl[]; +extern char datatoc_depth_frag_glsl[]; +extern char datatoc_depth_vert_glsl[]; extern char datatoc_conservative_depth_geom_glsl[]; extern char datatoc_common_view_lib_glsl[]; @@ -91,22 +91,28 @@ static void basic_engine_init(void *UNUSED(vedata)) /* Depth prepass */ if (!sh_data->depth) { - sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg); - const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; + + sh_data->depth = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg->lib, + datatoc_common_view_lib_glsl, + datatoc_depth_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg->def, NULL}, + }); + sh_data->depth_conservative = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg->lib, datatoc_common_view_lib_glsl, - datatoc_conservative_depth_vert_glsl, + datatoc_depth_vert_glsl, NULL}, .geom = (const char *[]){sh_cfg->lib, datatoc_common_view_lib_glsl, datatoc_conservative_depth_geom_glsl, NULL}, - .frag = (const char *[]){datatoc_common_view_lib_glsl, - datatoc_conservative_depth_frag_glsl, - NULL}, - .defs = (const char *[]){sh_cfg->def, NULL}, + .frag = (const char *[]){datatoc_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg->def, "#define CONSERVATIVE_RASTER\n", NULL}, }); } } @@ -233,6 +239,7 @@ static void basic_engine_free(void) { for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) { BASIC_Shaders *sh_data = &e_data.sh_data[i]; + DRW_SHADER_FREE_SAFE(sh_data->depth); DRW_SHADER_FREE_SAFE(sh_data->depth_conservative); } } diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl b/source/blender/draw/engines/basic/shaders/depth_frag.glsl index ff4a015c335..ff4a015c335 100644 --- a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl +++ b/source/blender/draw/engines/basic/shaders/depth_frag.glsl diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl b/source/blender/draw/engines/basic/shaders/depth_vert.glsl index c55a3211ff2..318d0acef6f 100644 --- a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl +++ b/source/blender/draw/engines/basic/shaders/depth_vert.glsl @@ -1,12 +1,16 @@ +#ifdef CONSERVATIVE_RASTER RESOURCE_ID_VARYING +#endif in vec3 pos; void main() { GPU_INTEL_VERTEX_SHADER_WORKAROUND +#ifdef CONSERVATIVE_RASTER PASS_RESOURCE_ID +#endif vec3 world_pos = point_object_to_world(pos); gl_Position = point_world_to_ndc(world_pos); diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 6874947de55..a19af77124f 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -24,6 +24,8 @@ #include "DRW_render.h" +#include "BLI_memblock.h" + #include "eevee_lightcache.h" #include "eevee_private.h" @@ -54,8 +56,17 @@ void EEVEE_view_layer_data_free(void *storage) DRW_UBO_FREE_SAFE(sldata->grid_ubo); DRW_UBO_FREE_SAFE(sldata->planar_ubo); DRW_UBO_FREE_SAFE(sldata->common_ubo); - for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) { - DRW_UBO_FREE_SAFE(sldata->renderpass_ubo[i]); + + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.combined); + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_color); + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_light); + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_color); + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_light); + DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.emit); + + if (sldata->material_cache) { + BLI_memblock_destroy(sldata->material_cache, NULL); + sldata->material_cache = NULL; } } diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index ec6770e4549..4a3cc36ddef 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -31,6 +31,8 @@ #include "BKE_camera.h" +#include "BLI_string_utils.h" + #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -48,24 +50,28 @@ static struct { extern char datatoc_effect_dof_vert_glsl[]; extern char datatoc_effect_dof_frag_glsl[]; +extern char datatoc_common_view_lib_glsl[]; + static void eevee_create_shader_depth_of_field(const bool use_alpha) { + char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl, datatoc_effect_dof_frag_glsl); e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen( - datatoc_effect_dof_frag_glsl, + frag, use_alpha ? "#define USE_ALPHA_DOF\n" "#define STEP_DOWNSAMPLE\n" : "#define STEP_DOWNSAMPLE\n"); e_data.dof_scatter_sh[use_alpha] = DRW_shader_create(datatoc_effect_dof_vert_glsl, NULL, - datatoc_effect_dof_frag_glsl, + frag, use_alpha ? "#define USE_ALPHA_DOF\n" "#define STEP_SCATTER\n" : "#define STEP_SCATTER\n"); - e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(datatoc_effect_dof_frag_glsl, + e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(frag, use_alpha ? "#define USE_ALPHA_DOF\n" "#define STEP_RESOLVE\n" : "#define STEP_RESOLVE\n"); + MEM_freeN(frag); } int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 05b18da4374..ab846fe0f11 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -333,8 +333,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv); DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat); DRW_shgroup_call(grp, quad, NULL); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index a1112eb92df..b698574f9d7 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -88,7 +88,7 @@ static void eevee_engine_init(void *ved) * `EEVEE_effects_init` needs to go second for TAA. */ EEVEE_renderpasses_init(vedata); EEVEE_effects_init(sldata, vedata, camera, false); - EEVEE_materials_init(sldata, stl, fbl); + EEVEE_materials_init(sldata, vedata, stl, fbl); EEVEE_shadows_init(sldata); EEVEE_lightprobes_init(sldata, vedata); } @@ -230,7 +230,7 @@ static void eevee_draw_scene(void *vedata) BLI_halton_3d(primes, offset, samp, r); EEVEE_update_noise(psl, fbl, r); EEVEE_volumes_set_jitter(sldata, samp - 1); - EEVEE_materials_init(sldata, stl, fbl); + EEVEE_materials_init(sldata, vedata, stl, fbl); } /* Copy previous persmat to UBO data */ copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat); @@ -274,8 +274,7 @@ static void eevee_draw_scene(void *vedata) /* Depth prepass */ DRW_stats_group_start("Prepass"); - DRW_draw_pass(psl->depth_pass); - DRW_draw_pass(psl->depth_pass_cull); + DRW_draw_pass(psl->depth_ps); DRW_stats_group_end(); /* Create minmax texture */ @@ -289,9 +288,9 @@ static void eevee_draw_scene(void *vedata) /* Shading pass */ DRW_stats_group_start("Shading"); if (DRW_state_draw_background()) { - DRW_draw_pass(psl->background_pass); + DRW_draw_pass(psl->background_ps); } - EEVEE_materials_draw_opaque(sldata, psl); + DRW_draw_pass(psl->material_ps); EEVEE_subsurface_data_render(sldata, vedata); DRW_stats_group_end(); @@ -306,9 +305,8 @@ static void eevee_draw_scene(void *vedata) /* Opaque refraction */ DRW_stats_group_start("Opaque Refraction"); - DRW_draw_pass(psl->refract_depth_pass); - DRW_draw_pass(psl->refract_depth_pass_cull); - DRW_draw_pass(psl->refract_pass); + DRW_draw_pass(psl->depth_refract_ps); + DRW_draw_pass(psl->material_refract_ps); DRW_stats_group_end(); /* Volumetrics Resolve Opaque */ diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 614c749b9aa..4cdd166f09c 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -379,9 +379,7 @@ static bool eevee_lightcache_static_load(LightCache *lcache) 0, false, NULL); - GPU_texture_bind(lcache->grid_tx.tex, 0); GPU_texture_filter_mode(lcache->grid_tx.tex, true); - GPU_texture_unbind(lcache->grid_tx.tex); } if (lcache->cube_tx.tex == NULL) { @@ -406,13 +404,11 @@ static bool eevee_lightcache_static_load(LightCache *lcache) NULL); } - GPU_texture_bind(lcache->cube_tx.tex, 0); - GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true); for (int mip = 0; mip < lcache->mips_len; mip++) { GPU_texture_add_mipmap( lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data); } - GPU_texture_unbind(lcache->cube_tx.tex); + GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true); } return true; } @@ -822,7 +818,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb DRW_render_viewport_size_set(viewport_size); EEVEE_effects_init(sldata, vedata, NULL, true); - EEVEE_materials_init(sldata, stl, fbl); + EEVEE_materials_init(sldata, vedata, stl, fbl); EEVEE_shadows_init(sldata); EEVEE_lightprobes_init(sldata, vedata); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 3350c512b17..83b2a9bb6d4 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -248,8 +248,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call_instances(grp, NULL, geom, 6); @@ -271,8 +270,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -293,8 +291,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -337,51 +334,29 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat Scene *scene = draw_ctx->scene; World *wo = scene->world; - const float *col = G_draw.block.colorBackground; - /* LookDev */ EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo); - /* END */ + if (!grp && wo) { - col = &wo->horr; - - if (wo->use_nodes && wo->nodetree) { - static float error_col[3] = {1.0f, 0.0f, 1.0f}; - static float queue_col[3] = {0.5f, 0.5f, 0.5f}; - struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo); - - eGPUMaterialStatus status = GPU_material_status(gpumat); - - switch (status) { - case GPU_MAT_SUCCESS: - grp = DRW_shgroup_material_create(gpumat, psl->probe_background); - DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); - /* TODO (fclem): remove those (need to clean the GLSL files). */ - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); - DRW_shgroup_call(grp, geom, NULL); - break; - case GPU_MAT_QUEUED: - stl->g_data->queued_shaders_count++; - col = queue_col; - break; - default: - col = error_col; - break; - } - } + struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_PROBE); + + grp = DRW_shgroup_material_create(gpumat, psl->probe_background); + DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); + /* TODO (fclem): remove those (need to clean the GLSL files). */ + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); + DRW_shgroup_call(grp, geom, NULL); } /* Fallback if shader fails or if not using nodetree. */ if (grp == NULL) { grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background); - DRW_shgroup_uniform_vec3(grp, "color", col, 1); + DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1); DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); DRW_shgroup_call(grp, geom, NULL); } @@ -408,8 +383,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat /* TODO (fclem) get rid of those UBO. */ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call_procedural_triangles(grp, NULL, cube_len * 2); } @@ -436,8 +410,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(shgrp, "renderpass_block", sldata->renderpass_ubo.combined); int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2; DRW_shgroup_call_procedural_triangles(shgrp, NULL, tri_count); } @@ -455,8 +428,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(), psl->probe_display); DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance( grp, e_data.format_probe_display_planar, DRW_cache_quad_get()); @@ -923,12 +895,10 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat GPU_framebuffer_bind(face_fb[face]); GPU_framebuffer_clear_depth(face_fb[face], 1.0f); - DRW_draw_pass(psl->depth_pass); - DRW_draw_pass(psl->depth_pass_cull); + DRW_draw_pass(psl->depth_ps); DRW_draw_pass(psl->probe_background); - EEVEE_materials_draw_opaque(sldata, psl); - DRW_draw_pass(psl->sss_pass); /* Only output standard pass */ - DRW_draw_pass(psl->sss_pass_cull); + DRW_draw_pass(psl->material_ps); + DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */ DRW_draw_pass(psl->transparent_pass); } @@ -987,10 +957,8 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us /* Slight modification: we handle refraction as normal * shading and don't do SSRefraction. */ - DRW_draw_pass(psl->depth_pass_clip); - DRW_draw_pass(psl->depth_pass_clip_cull); - DRW_draw_pass(psl->refract_depth_pass_clip); - DRW_draw_pass(psl->refract_depth_pass_clip_cull); + DRW_draw_pass(psl->depth_ps); + DRW_draw_pass(psl->depth_refract_ps); DRW_draw_pass(psl->probe_background); EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer); @@ -999,10 +967,9 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us GPU_framebuffer_bind(fbl->planarref_fb); /* Shading pass */ - EEVEE_materials_draw_opaque(sldata, psl); - DRW_draw_pass(psl->sss_pass); /* Only output standard pass */ - DRW_draw_pass(psl->sss_pass_cull); - DRW_draw_pass(psl->refract_pass); + DRW_draw_pass(psl->material_ps); + DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */ + DRW_draw_pass(psl->material_refract_ps); /* Transparent */ if (DRW_state_is_image_render()) { diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index b33be750d80..18365d69514 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -34,6 +34,8 @@ #include "ED_screen.h" +#include "GPU_material.h" + #include "UI_resources.h" #include "eevee_lightcache.h" @@ -56,6 +58,43 @@ static void eevee_lookdev_lightcache_delete(EEVEE_Data *vedata) g_data->studiolight_rot_z = 0.0f; } +static void eevee_lookdev_hdri_preview_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) +{ + EEVEE_PassList *psl = vedata->psl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + DRWShadingGroup *grp; + + struct GPUBatch *sphere = DRW_cache_sphere_get(); + int mat_options = VAR_MAT_MESH | VAR_MAT_LOOKDEV; + + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | + DRW_STATE_CULL_BACK; + + { + Material *ma = EEVEE_material_default_diffuse_get(); + GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); + struct GPUShader *sh = GPU_material_get_shader(gpumat); + + DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state); + grp = DRW_shgroup_create(sh, psl->lookdev_diffuse_pass); + EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false); + DRW_shgroup_add_material_resources(grp, gpumat); + DRW_shgroup_call(grp, sphere, NULL); + } + { + Material *ma = EEVEE_material_default_glossy_get(); + GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); + struct GPUShader *sh = GPU_material_get_shader(gpumat); + + DRW_PASS_CREATE(psl->lookdev_glossy_pass, state); + grp = DRW_shgroup_create(sh, psl->lookdev_glossy_pass); + EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false); + DRW_shgroup_add_material_resources(grp, gpumat); + DRW_shgroup_call(grp, sphere, NULL); + } +} + void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, DRWShadingGroup **r_grp, @@ -106,6 +145,8 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, effects->anchor[1] = rect->ymin; EEVEE_temporal_sampling_reset(vedata); } + + eevee_lookdev_hdri_preview_init(vedata, sldata); } if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) { @@ -176,8 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); } DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); diff --git a/source/blender/draw/engines/eevee/eevee_lut_gen.c b/source/blender/draw/engines/eevee/eevee_lut_gen.c new file mode 100644 index 00000000000..5f20d6fbfb8 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_lut_gen.c @@ -0,0 +1,198 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2020, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + * + * EEVEE LUT generation: + * + * Routine to generate the LUT used by eevee stored in eevee_lut.h + * Theses functions are not to be used in the final executable. + */ + +#include "DRW_render.h" + +#include "BLI_alloca.h" +#include "BLI_rand.h" +#include "BLI_string_utils.h" + +extern char datatoc_bsdf_lut_frag_glsl[]; +extern char datatoc_btdf_lut_frag_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_bsdf_sampling_lib_glsl[]; +extern char datatoc_lightprobe_geom_glsl[]; +extern char datatoc_lightprobe_vert_glsl[]; + +static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) +{ + struct GPUTexture *tex; + struct GPUFrameBuffer *fb = NULL; + static float samples_len = 8192.0f; + static float inv_samples_len = 1.0f / 8192.0f; + + char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl); + + struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl, + datatoc_lightprobe_geom_glsl, + datatoc_bsdf_lut_frag_glsl, + lib_str, + "#define HAMMERSLEY_SIZE 8192\n" + "#define BRDF_LUT_SIZE 64\n" + "#define NOISE_SIZE 64\n"); + + DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1); + DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); + DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); + + struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); + DRW_shgroup_call(grp, geom, NULL); + + float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); + + tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels); + + DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER}; + GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1); + + GPU_framebuffer_bind(fb); + DRW_draw_pass(pass); + + float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut"); + glReadBuffer(GL_COLOR_ATTACHMENT0); + glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data); + + printf("{"); + for (int i = 0; i < w * h * 3; i += 3) { + printf("%ff, %ff, ", data[i], data[i + 1]); + i += 3; + printf("%ff, %ff, ", data[i], data[i + 1]); + i += 3; + printf("%ff, %ff, ", data[i], data[i + 1]); + i += 3; + printf("%ff, %ff, \n", data[i], data[i + 1]); + } + printf("}"); + + MEM_freeN(texels); + MEM_freeN(data); + + return tex; +} + +static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) +{ + struct GPUTexture *tex; + struct GPUTexture *hammersley = create_hammersley_sample_texture(8192); + struct GPUFrameBuffer *fb = NULL; + static float samples_len = 8192.0f; + static float a2 = 0.0f; + static float inv_samples_len = 1.0f / 8192.0f; + + char *frag_str = BLI_string_joinN( + datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl); + + struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str, + "#define HAMMERSLEY_SIZE 8192\n" + "#define BRDF_LUT_SIZE 64\n" + "#define NOISE_SIZE 64\n" + "#define LUT_SIZE 64\n"); + + MEM_freeN(frag_str); + + DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); + DRW_shgroup_uniform_float(grp, "a2", &a2, 1); + DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1); + DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley); + DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex); + + struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); + DRW_shgroup_call(grp, geom, NULL); + + float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); + + tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels); + + DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER}; + GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1); + + GPU_framebuffer_bind(fb); + + float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut"); + + float inc = 1.0f / 31.0f; + float roughness = 1e-8f - inc; + FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w"); + fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n"); + do { + roughness += inc; + CLAMP(roughness, 1e-4f, 1.0f); + a2 = powf(roughness, 4.0f); + DRW_draw_pass(pass); + + GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data); + +#if 1 + fprintf(f, "\t{\n\t\t"); + for (int i = 0; i < w * h * 3; i += 3) { + fprintf(f, "%ff,", data[i]); + if (((i / 3) + 1) % 12 == 0) { + fprintf(f, "\n\t\t"); + } + else { + fprintf(f, " "); + } + } + fprintf(f, "\n\t},\n"); +#else + for (int i = 0; i < w * h * 3; i += 3) { + if (data[i] < 0.01) { + printf(" "); + } + else if (data[i] < 0.3) { + printf("."); + } + else if (data[i] < 0.6) { + printf("+"); + } + else if (data[i] < 0.9) { + printf("%%"); + } + else { + printf("#"); + } + if ((i / 3 + 1) % 64 == 0) { + printf("\n"); + } + } +#endif + + } while (roughness < 1.0f); + fprintf(f, "\n};\n"); + + fclose(f); + + MEM_freeN(texels); + MEM_freeN(data); + + return tex; +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 03cdb02a48a..0f10fb0ef53 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -23,10 +23,10 @@ #include "DRW_render.h" #include "BLI_alloca.h" -#include "BLI_dynstr.h" #include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math_bits.h" +#include "BLI_memblock.h" #include "BLI_rand.h" #include "BLI_string_utils.h" @@ -48,29 +48,11 @@ /* *********** STATIC *********** */ static struct { - char *frag_shader_lib; - char *vert_shader_str; - char *vert_shadow_shader_str; - char *vert_background_shader_str; - char *vert_volume_shader_str; - char *geom_volume_shader_str; - char *volume_shader_lib; - - struct GPUShader *default_prepass_sh; - struct GPUShader *default_prepass_clip_sh; - struct GPUShader *default_hair_prepass_sh; - struct GPUShader *default_hair_prepass_clip_sh; - struct GPUShader *default_lit[VAR_MAT_MAX]; - struct GPUShader *default_background; - struct GPUShader *update_noise_sh; - /* 64*64 array texture containing all LUTs and other utilitarian arrays. * Packing enables us to same precious textures slots. */ struct GPUTexture *util_tex; struct GPUTexture *noise_tex; - uint sss_count; - float noise_offsets[3]; } e_data = {NULL}; /* Engine data */ @@ -82,8 +64,6 @@ extern char datatoc_prepass_vert_glsl[]; extern char datatoc_default_frag_glsl[]; extern char datatoc_default_world_frag_glsl[]; extern char datatoc_ltc_lib_glsl[]; -extern char datatoc_bsdf_lut_frag_glsl[]; -extern char datatoc_btdf_lut_frag_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; extern char datatoc_bsdf_sampling_lib_glsl[]; extern char datatoc_common_uniforms_lib_glsl[]; @@ -107,320 +87,45 @@ extern char datatoc_volumetric_frag_glsl[]; extern char datatoc_volumetric_lib_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; -#define DEFAULT_RENDER_PASS_FLAG 0xefffffff - -/* Iterator for render passes. This iteration will only do the material based render passes. it - * will ignore `EEVEE_RENDER_PASS_ENVIRONMENT`. - * - * parameters: - * - `render_passes_` is a bitflag for render_passes that needs to be iterated over. - * - `render_pass_index_` is a parameter name where the index of the render_pass will be available - * during iteration. This index can be used to select the right pass in the `psl`. - * - `render_pass_` is the bitflag of the render_pass of the current iteration. - * - * The `render_pass_index_` parameter needs to be the same for the `RENDER_PASS_ITER_BEGIN` and - * `RENDER_PASS_ITER_END`. - */ -#define RENDER_PASS_ITER_BEGIN(render_passes_, render_pass_index_, render_pass_) \ - const eViewLayerEEVEEPassType __filtered_##render_pass_index_ = render_passes_ & \ - EEVEE_RENDERPASSES_MATERIAL & \ - ~EEVEE_RENDER_PASS_ENVIRONMENT; \ - if (__filtered_##render_pass_index_ != 0) { \ - int render_pass_index_ = 1; \ - for (int bit_##render_pass_ = 0; bit_##render_pass_ < EEVEE_RENDER_PASS_MAX_BIT; \ - bit_##render_pass_++) { \ - eViewLayerEEVEEPassType render_pass_ = (1 << bit_##render_pass_); \ - if ((__filtered_##render_pass_index_ & render_pass_) != 0) { -#define RENDER_PASS_ITER_END(render_pass_index_) \ - render_pass_index_ += 1; \ - } \ - } \ - } \ - ((void)0) +typedef struct EeveeMaterialCache { + struct DRWShadingGroup *depth_grp; + struct DRWShadingGroup *shading_grp; + struct DRWShadingGroup *shadow_grp; + struct GPUMaterial *shading_gpumat; + /* Meh, Used by hair to ensure draw order when calling DRW_shgroup_create_sub. + * Pointers to ghash values. */ + struct DRWShadingGroup **depth_grp_p; + struct DRWShadingGroup **shading_grp_p; + struct DRWShadingGroup **shadow_grp_p; +} EeveeMaterialCache; /* *********** FUNCTIONS *********** */ -#if 0 /* Used only to generate the LUT values */ -static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) -{ - struct GPUTexture *tex; - struct GPUFrameBuffer *fb = NULL; - static float samples_len = 8192.0f; - static float inv_samples_len = 1.0f / 8192.0f; - - char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl); - - struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl, - datatoc_lightprobe_geom_glsl, - datatoc_bsdf_lut_frag_glsl, - lib_str, - "#define HAMMERSLEY_SIZE 8192\n" - "#define BRDF_LUT_SIZE 64\n" - "#define NOISE_SIZE 64\n"); - - DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1); - DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1); - DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); - DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); - - struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call(grp, geom, NULL); - - float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); - - tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels); - - DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER}; - GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1); - - GPU_framebuffer_bind(fb); - DRW_draw_pass(pass); - - float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut"); - glReadBuffer(GL_COLOR_ATTACHMENT0); - glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data); - - printf("{"); - for (int i = 0; i < w * h * 3; i += 3) { - printf("%ff, %ff, ", data[i], data[i + 1]); - i += 3; - printf("%ff, %ff, ", data[i], data[i + 1]); - i += 3; - printf("%ff, %ff, ", data[i], data[i + 1]); - i += 3; - printf("%ff, %ff, \n", data[i], data[i + 1]); - } - printf("}"); - - MEM_freeN(texels); - MEM_freeN(data); - - return tex; -} - -static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) -{ - struct GPUTexture *tex; - struct GPUTexture *hammersley = create_hammersley_sample_texture(8192); - struct GPUFrameBuffer *fb = NULL; - static float samples_len = 8192.0f; - static float a2 = 0.0f; - static float inv_samples_len = 1.0f / 8192.0f; - - char *frag_str = BLI_string_joinN( - datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl); - - struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str, - "#define HAMMERSLEY_SIZE 8192\n" - "#define BRDF_LUT_SIZE 64\n" - "#define NOISE_SIZE 64\n" - "#define LUT_SIZE 64\n"); - - MEM_freeN(frag_str); - - DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_float(grp, "a2", &a2, 1); - DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1); - DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1); - DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley); - DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex); - - struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - DRW_shgroup_call(grp, geom, NULL); - - float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut"); - - tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels); - - DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER}; - GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1); - - GPU_framebuffer_bind(fb); - - float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut"); - - float inc = 1.0f / 31.0f; - float roughness = 1e-8f - inc; - FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w"); - fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n"); - do { - roughness += inc; - CLAMP(roughness, 1e-4f, 1.0f); - a2 = powf(roughness, 4.0f); - DRW_draw_pass(pass); - - GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data); - -# if 1 - fprintf(f, "\t{\n\t\t"); - for (int i = 0; i < w * h * 3; i += 3) { - fprintf(f, "%ff,", data[i]); - if (((i / 3) + 1) % 12 == 0) { - fprintf(f, "\n\t\t"); - } - else { - fprintf(f, " "); - } - } - fprintf(f, "\n\t},\n"); -# else - for (int i = 0; i < w * h * 3; i += 3) { - if (data[i] < 0.01) { - printf(" "); - } - else if (data[i] < 0.3) { - printf("."); - } - else if (data[i] < 0.6) { - printf("+"); - } - else if (data[i] < 0.9) { - printf("%%"); - } - else { - printf("#"); - } - if ((i / 3 + 1) % 64 == 0) { - printf("\n"); - } - } -# endif - - } while (roughness < 1.0f); - fprintf(f, "\n};\n"); - - fclose(f); - - MEM_freeN(texels); - MEM_freeN(data); - - return tex; -} -#endif /* XXX TODO define all shared resources in a shared place without duplication */ struct GPUTexture *EEVEE_materials_get_util_tex(void) { return e_data.util_tex; } -static char *eevee_get_defines(int options) -{ - char *str = NULL; - - DynStr *ds = BLI_dynstr_new(); - BLI_dynstr_append(ds, SHADER_DEFINES); - - if ((options & VAR_MAT_MESH) != 0) { - BLI_dynstr_append(ds, "#define MESH_SHADER\n"); - } - if ((options & VAR_MAT_HAIR) != 0) { - BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); - } - if ((options & VAR_MAT_PROBE) != 0) { - BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n"); - } - if ((options & VAR_MAT_CLIP) != 0) { - BLI_dynstr_append(ds, "#define USE_ALPHA_CLIP\n"); - } - if ((options & VAR_MAT_SHADOW) != 0) { - BLI_dynstr_append(ds, "#define SHADOW_SHADER\n"); - } - if ((options & VAR_MAT_HASH) != 0) { - BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n"); - } - if ((options & VAR_MAT_BLEND) != 0) { - BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n"); - } - if ((options & VAR_MAT_MULT) != 0) { - BLI_dynstr_append(ds, "#define USE_MULTIPLY\n"); - } - if ((options & VAR_MAT_REFRACT) != 0) { - BLI_dynstr_append(ds, "#define USE_REFRACTION\n"); - } - if ((options & VAR_MAT_LOOKDEV) != 0) { - BLI_dynstr_append(ds, "#define LOOKDEV\n"); - } - if ((options & VAR_MAT_HOLDOUT) != 0) { - BLI_dynstr_append(ds, "#define HOLDOUT\n"); - } - - str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - return str; -} - -static char *eevee_get_volume_defines(int options) -{ - char *str = NULL; - - DynStr *ds = BLI_dynstr_new(); - BLI_dynstr_append(ds, SHADER_DEFINES); - BLI_dynstr_append(ds, "#define VOLUMETRICS\n"); - - if ((options & VAR_MAT_VOLUME) != 0) { - BLI_dynstr_append(ds, "#define MESH_SHADER\n"); - } - - str = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - return str; -} - -/* Get the default render pass ubo. This is a ubo that enables all bsdf render passes. */ -struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata) -{ - return sldata->renderpass_ubo[0]; -} - -/* Get the render pass ubo for rendering the given render_pass. */ -static struct GPUUniformBuffer *get_render_pass_ubo(EEVEE_ViewLayerData *sldata, - eViewLayerEEVEEPassType render_pass) -{ - int index; - switch (render_pass) { - case EEVEE_RENDER_PASS_DIFFUSE_COLOR: - index = 1; - break; - case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: - index = 2; - break; - case EEVEE_RENDER_PASS_SPECULAR_COLOR: - index = 3; - break; - case EEVEE_RENDER_PASS_SPECULAR_LIGHT: - index = 4; - break; - case EEVEE_RENDER_PASS_EMIT: - index = 5; - break; - default: - index = 0; - break; - } - return sldata->renderpass_ubo[index]; -} /** * ssr_id can be null to disable ssr contribution. */ -static void add_standard_uniforms(DRWShadingGroup *shgrp, - EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - int *ssr_id, - float *refract_depth, - bool use_diffuse, - bool use_glossy, - bool use_refract, - bool use_ssrefraction, - bool use_alpha_blend, - eViewLayerEEVEEPassType render_pass) +void EEVEE_material_bind_resources(DRWShadingGroup *shgrp, + GPUMaterial *gpumat, + EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + int *ssr_id, + float *refract_depth, + bool use_ssrefraction, + bool use_alpha_blend) { + bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE); + bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY); + bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT); + LightCache *lcache = vedata->stl->g_data->light_cache; EEVEE_EffectsInfo *effects = vedata->stl->effects; + EEVEE_PrivateData *pd = vedata->stl->g_data; DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); @@ -428,11 +133,11 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(shgrp, "renderpass_block", get_render_pass_ubo(sldata, render_pass)); + DRW_shgroup_uniform_block_ref(shgrp, "renderpass_block", &pd->renderpass_ubo); DRW_shgroup_uniform_int_copy(shgrp, "outputSssId", 1); + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); if (use_diffuse || use_glossy || use_refract) { - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool); DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool); DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer); @@ -463,36 +168,6 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, } } -/* Add the uniforms for the background shader to `shgrp`. */ -static void add_background_uniforms(DRWShadingGroup *shgrp, - EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata) -{ - EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; - DRW_shgroup_uniform_float(shgrp, "backgroundAlpha", &stl->g_data->background_alpha, 1); - /* TODO (fclem): remove those (need to clean the GLSL files). */ - DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block( - shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); -} - -static void create_default_shader(int options) -{ - char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_default_frag_glsl); - - char *defines = eevee_get_defines(options); - - e_data.default_lit[options] = DRW_shader_create(e_data.vert_shader_str, NULL, frag_str, defines); - - MEM_freeN(defines); - MEM_freeN(frag_str); -} - static void eevee_init_noise_texture(void) { e_data.noise_tex = DRW_texture_create_2d(64, 64, GPU_RGBA16F, 0, (float *)blue_noise); @@ -559,8 +234,6 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d e_data.noise_offsets[1] = offsets[1]; e_data.noise_offsets[2] = offsets[2]; - /* Attach & detach because we don't currently support multiple FB per texture, - * and this would be the case for multiple viewport. */ GPU_framebuffer_bind(fbl->update_noise_fb); DRW_draw_pass(psl->update_noise_pass); } @@ -606,94 +279,15 @@ void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_vi } void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl) { const DRWContextState *draw_ctx = DRW_context_state_get(); EEVEE_PrivateData *g_data = stl->g_data; - if (!e_data.frag_shader_lib) { - /* Shaders */ - e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_bsdf_sampling_lib_glsl, - datatoc_ambient_occlusion_lib_glsl, - datatoc_raytrace_lib_glsl, - datatoc_ssr_lib_glsl, - datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_irradiance_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_ltc_lib_glsl, - datatoc_lights_lib_glsl, - /* Add one for each Closure */ - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_lit_surface_frag_glsl, - datatoc_volumetric_lib_glsl); - - e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_common_uniforms_lib_glsl, - datatoc_bsdf_common_lib_glsl, - datatoc_ambient_occlusion_lib_glsl, - datatoc_octahedron_lib_glsl, - datatoc_cubemap_lib_glsl, - datatoc_irradiance_lib_glsl, - datatoc_lightprobe_lib_glsl, - datatoc_ltc_lib_glsl, - datatoc_lights_lib_glsl, - datatoc_volumetric_lib_glsl, - datatoc_volumetric_frag_glsl); - - e_data.vert_shader_str = BLI_string_joinN( - datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl); - - e_data.vert_shadow_shader_str = BLI_string_joinN( - datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl); - - e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_background_vert_glsl); - - e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_volumetric_vert_glsl); - - e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, - datatoc_volumetric_geom_glsl); - - e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl, - NULL, - datatoc_default_world_frag_glsl, - datatoc_common_view_lib_glsl, - NULL); - - char *vert_str = BLI_string_joinN( - datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl); - - e_data.default_prepass_sh = DRW_shader_create(vert_str, NULL, datatoc_prepass_frag_glsl, NULL); - - e_data.default_prepass_clip_sh = DRW_shader_create( - vert_str, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n"); - - e_data.default_hair_prepass_sh = DRW_shader_create( - vert_str, NULL, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n"); - - e_data.default_hair_prepass_clip_sh = DRW_shader_create(vert_str, - NULL, - datatoc_prepass_frag_glsl, - "#define HAIR_SHADER\n" - "#define CLIP_PLANES\n"); - MEM_freeN(vert_str); - - e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL); + if (!e_data.util_tex) { + EEVEE_shaders_material_shaders_init(); eevee_init_util_texture(); eevee_init_noise_texture(); @@ -728,33 +322,36 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, { /* Create RenderPass UBO */ - if (sldata->renderpass_ubo[0] == NULL) { - /* EEVEE_RENDER_PASS_COMBINED */ - sldata->renderpass_data[0] = (const EEVEE_RenderPassData){ - true, true, true, true, true, false}; - /* EEVEE_RENDER_PASS_DIFFUSE_COLOR */ - sldata->renderpass_data[1] = (const EEVEE_RenderPassData){ - true, false, false, false, false, true}; - /* EEVEE_RENDER_PASS_DIFFUSE_LIGHT */ - sldata->renderpass_data[2] = (const EEVEE_RenderPassData){ - true, true, false, false, false, false}; - /* EEVEE_RENDER_PASS_SPECULAR_COLOR */ - sldata->renderpass_data[3] = (const EEVEE_RenderPassData){ - false, false, true, false, false, false}; - /* EEVEE_RENDER_PASS_SPECULAR_LIGHT */ - sldata->renderpass_data[4] = (const EEVEE_RenderPassData){ - false, false, true, true, false, false}; - /* EEVEE_RENDER_PASS_EMIT */ - sldata->renderpass_data[5] = (const EEVEE_RenderPassData){ - false, false, false, false, true, false}; - - for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) { - sldata->renderpass_ubo[i] = DRW_uniformbuffer_create(sizeof(EEVEE_RenderPassData), - &sldata->renderpass_data[i]); - } + if (sldata->renderpass_ubo.combined == NULL) { + sldata->renderpass_ubo.combined = DRW_uniformbuffer_create( + sizeof(EEVEE_RenderPassData), + &(const EEVEE_RenderPassData){true, true, true, true, true, false}); + + sldata->renderpass_ubo.diff_color = DRW_uniformbuffer_create( + sizeof(EEVEE_RenderPassData), + &(const EEVEE_RenderPassData){true, false, false, false, false, true}); + + sldata->renderpass_ubo.diff_light = DRW_uniformbuffer_create( + sizeof(EEVEE_RenderPassData), + &(const EEVEE_RenderPassData){true, true, false, false, false, false}); + + sldata->renderpass_ubo.spec_color = DRW_uniformbuffer_create( + sizeof(EEVEE_RenderPassData), + &(const EEVEE_RenderPassData){false, false, true, false, false, false}); + + sldata->renderpass_ubo.spec_light = DRW_uniformbuffer_create( + sizeof(EEVEE_RenderPassData), + &(const EEVEE_RenderPassData){false, false, true, true, false, false}); + + sldata->renderpass_ubo.emit = DRW_uniformbuffer_create( + sizeof(EEVEE_RenderPassData), + &(const EEVEE_RenderPassData){false, false, false, false, true, false}); } - /* HACK: EEVEE_material_world_background_get can create a new context. This can only be + /* Used combined pass by default. */ + g_data->renderpass_ubo = sldata->renderpass_ubo.combined; + + /* HACK: EEVEE_material_get can create a new context. This can only be * done when there is no active framebuffer. We do this here otherwise * `EEVEE_renderpasses_output_init` will fail. It cannot be done in * `EEVEE_renderpasses_init` as the `e_data.vertcode` can be uninitialized. @@ -763,414 +360,12 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, struct Scene *scene = draw_ctx->scene; struct World *wo = scene->world; if (wo && wo->use_nodes) { - EEVEE_material_world_background_get(scene, wo); + EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND); } } } } -struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - const int options = VAR_WORLD_PROBE; - - GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, false); - if (mat != NULL) { - return mat; - } - return DRW_shader_create_from_world(scene, - wo, - engine, - options, - false, - e_data.vert_background_shader_str, - NULL, - e_data.frag_shader_lib, - SHADER_DEFINES "#define PROBE_CAPTURE\n", - false); -} - -struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, World *wo) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - int options = VAR_WORLD_BACKGROUND; - - GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true); - if (mat != NULL) { - return mat; - } - return DRW_shader_create_from_world(scene, - wo, - engine, - options, - false, - e_data.vert_background_shader_str, - NULL, - e_data.frag_shader_lib, - SHADER_DEFINES "#define WORLD_BACKGROUND\n", - true); -} - -struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - int options = VAR_WORLD_VOLUME; - - GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true); - if (mat != NULL) { - return mat; - } - - char *defines = eevee_get_volume_defines(options); - - mat = DRW_shader_create_from_world(scene, - wo, - engine, - options, - true, - e_data.vert_volume_shader_str, - e_data.geom_volume_shader_str, - e_data.volume_shader_lib, - defines, - true); - - MEM_freeN(defines); - - return mat; -} - -struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene, - Material *ma, - EEVEE_Data *UNUSED(vedata), - bool use_blend, - bool use_refract) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - int options = VAR_MAT_MESH; - - SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND); - SET_FLAG_FROM_TEST(options, use_refract, VAR_MAT_REFRACT); - - GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true); - if (mat) { - return mat; - } - - char *defines = eevee_get_defines(options); - - mat = DRW_shader_create_from_material(scene, - ma, - engine, - options, - false, - e_data.vert_shader_str, - NULL, - e_data.frag_shader_lib, - defines, - true); - - MEM_freeN(defines); - - return mat; -} - -struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - int options = VAR_MAT_VOLUME; - - GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true); - if (mat != NULL) { - return mat; - } - - char *defines = eevee_get_volume_defines(options); - - mat = DRW_shader_create_from_material(scene, - ma, - engine, - options, - true, - e_data.vert_volume_shader_str, - e_data.geom_volume_shader_str, - e_data.volume_shader_lib, - defines, - true); - - MEM_freeN(defines); - - return mat; -} - -struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, - Material *ma, - bool use_hashed_alpha, - bool is_shadow) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - int options = VAR_MAT_MESH; - - SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH); - SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP); - SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW); - - GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true); - if (mat) { - return mat; - } - - char *defines = eevee_get_defines(options); - - char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl); - - mat = DRW_shader_create_from_material(scene, - ma, - engine, - options, - false, - (is_shadow) ? e_data.vert_shadow_shader_str : - e_data.vert_shader_str, - NULL, - frag_str, - defines, - true); - - MEM_freeN(frag_str); - MEM_freeN(defines); - - return mat; -} - -static struct GPUMaterial *EEVEE_material_hair_depth_get(struct Scene *scene, - Material *ma, - bool use_hashed_alpha, - bool is_shadow) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - int options = VAR_MAT_MESH | VAR_MAT_HAIR; - - SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH); - SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP); - SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW); - - GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true); - if (mat) { - return mat; - } - - char *defines = eevee_get_defines(options); - - char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl); - - mat = DRW_shader_create_from_material(scene, - ma, - engine, - options, - false, - (is_shadow) ? e_data.vert_shadow_shader_str : - e_data.vert_shader_str, - NULL, - frag_str, - defines, - false); - - MEM_freeN(frag_str); - MEM_freeN(defines); - - return mat; -} - -struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma) -{ - const void *engine = &DRW_engine_viewport_eevee_type; - int options = VAR_MAT_MESH | VAR_MAT_HAIR; - - GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true); - if (mat) { - return mat; - } - - char *defines = eevee_get_defines(options); - - mat = DRW_shader_create_from_material(scene, - ma, - engine, - options, - false, - e_data.vert_shader_str, - NULL, - e_data.frag_shader_lib, - defines, - true); - - MEM_freeN(defines); - - return mat; -} - -/** - * Create a default shading group inside the given pass. - */ -static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - DRWPass *pass, - bool is_hair, - bool use_blend, - bool use_ssr) -{ - static int ssr_id; - ssr_id = (use_ssr) ? 1 : -1; - int options = VAR_MAT_MESH; - - SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR); - SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND); - - if (e_data.default_lit[options] == NULL) { - create_default_shader(options); - } - - DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass); - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - true, - true, - false, - false, - use_blend, - DEFAULT_RENDER_PASS_FLAG); - - return shgrp; -} - -/** - * Create a default shading group inside the default pass without standard uniforms. - */ -static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - Object *ob, - ParticleSystem *psys, - ModifierData *md, - bool is_hair, - bool holdout, - bool use_ssr) -{ - static int ssr_id; - ssr_id = (use_ssr) ? 1 : -1; - int options = VAR_MAT_MESH; - - EEVEE_PassList *psl = vedata->psl; - - BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR))); - - SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR); - SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT); - - if (e_data.default_lit[options] == NULL) { - create_default_shader(options); - } - - if (psl->default_pass[options] == NULL) { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES; - DRW_PASS_CREATE(psl->default_pass[options], state); - - /* XXX / WATCH: This creates non persistent binds for the ubos and textures. - * But it's currently OK because the following shgroups does not add any bind. - * EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */ - if (!is_hair) { - DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], - psl->default_pass[options]); - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - true, - true, - false, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - } - } - - if (is_hair) { - DRWShadingGroup *shgrp = DRW_shgroup_hair_create( - ob, psys, md, vedata->psl->default_pass[options], e_data.default_lit[options]); - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - true, - true, - false, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - return shgrp; - } - else { - return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); - } -} - -static struct DRWShadingGroup *EEVEE_default_render_pass_shading_group_get( - EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - bool holdout, - bool use_ssr, - DRWPass *pass, - eViewLayerEEVEEPassType render_pass_flag) -{ - static int ssr_id; - ssr_id = (use_ssr) ? 1 : -1; - int options = VAR_MAT_MESH; - - SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT); - - if (e_data.default_lit[options] == NULL) { - create_default_shader(options); - } - - DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass); - add_standard_uniforms( - shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag); - return shgrp; -} - -static struct DRWShadingGroup *EEVEE_default_hair_render_pass_shading_group_get( - EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - Object *ob, - ParticleSystem *psys, - ModifierData *md, - bool holdout, - bool use_ssr, - DRWPass *pass, - eViewLayerEEVEEPassType render_pass_flag) -{ - static int ssr_id; - ssr_id = (use_ssr) ? 1 : -1; - int options = VAR_MAT_MESH | VAR_MAT_HAIR; - - BLI_assert((ob && psys && md)); - - SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT); - - if (e_data.default_lit[options] == NULL) { - create_default_shader(options); - } - - DRWShadingGroup *shgrp = DRW_shgroup_hair_create( - ob, psys, md, pass, e_data.default_lit[options]); - add_standard_uniforms( - shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag); - return shgrp; -} - void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; @@ -1180,10 +375,17 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Create Material Ghash */ { stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash"); + + if (sldata->material_cache == NULL) { + sldata->material_cache = BLI_memblock_create(sizeof(EeveeMaterialCache)); + } + else { + BLI_memblock_clear(sldata->material_cache, NULL); + } } { - DRW_PASS_CREATE(psl->background_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); + DRW_PASS_CREATE(psl->background_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = NULL; @@ -1191,485 +393,297 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) Scene *scene = draw_ctx->scene; World *wo = scene->world; - const float *col = G_draw.block.colorBackground; - - EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_pass, wo, NULL); + EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_ps, wo, NULL); if (!grp && wo) { - col = &wo->horr; - - if (wo->use_nodes && wo->nodetree) { - static float error_col[3] = {1.0f, 0.0f, 1.0f}; - static float compile_col[3] = {0.5f, 0.5f, 0.5f}; - struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo); - - switch (GPU_material_status(gpumat)) { - case GPU_MAT_SUCCESS: - grp = DRW_shgroup_material_create(gpumat, psl->background_pass); - add_background_uniforms(grp, sldata, vedata); - DRW_shgroup_call(grp, geom, NULL); - break; - case GPU_MAT_QUEUED: - /* TODO Bypass probe compilation. */ - stl->g_data->queued_shaders_count++; - col = compile_col; - break; - case GPU_MAT_FAILED: - default: - col = error_col; - break; - } - } + struct GPUMaterial *gpumat = EEVEE_material_get( + vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND); + + grp = DRW_shgroup_material_create(gpumat, psl->background_ps); + DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); + /* TODO (fclem): remove those (need to clean the GLSL files). */ + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); + DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); + DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); + DRW_shgroup_call(grp, geom, NULL); } /* Fallback if shader fails or if not using nodetree. */ if (grp == NULL) { - grp = DRW_shgroup_create(e_data.default_background, psl->background_pass); - DRW_shgroup_uniform_vec3(grp, "color", col, 1); + GPUShader *sh = EEVEE_shaders_default_background_sh_get(); + grp = DRW_shgroup_create(sh, psl->background_ps); + DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1); DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1); DRW_shgroup_call(grp, geom, NULL); } } - { - DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - DRW_PASS_CREATE(psl->depth_pass, state); - stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass); - - state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; - DRW_PASS_CREATE(psl->depth_pass_cull, state); - stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh, - psl->depth_pass_cull); - - state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES; - DRW_PASS_CREATE(psl->depth_pass_clip, state); - stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, - psl->depth_pass_clip); - - state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | - DRW_STATE_CULL_BACK; - DRW_PASS_CREATE(psl->depth_pass_clip_cull, state); - stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh, - psl->depth_pass_clip_cull); - } +#define EEVEE_PASS_CREATE(pass, state) \ + do { \ + DRW_PASS_CREATE(psl->pass##_ps, state); \ + DRW_PASS_CREATE(psl->pass##_cull_ps, state | DRW_STATE_CULL_BACK); \ + DRW_pass_link(psl->pass##_ps, psl->pass##_cull_ps); \ + } while (0) - { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES; - DRW_PASS_CREATE(psl->material_pass, state); - DRW_PASS_CREATE(psl->material_pass_cull, state | DRW_STATE_CULL_BACK); - } +#define EEVEE_CLIP_PASS_CREATE(pass, state) \ + do { \ + DRWState st = state | DRW_STATE_CLIP_PLANES; \ + DRW_PASS_INSTANCE_CREATE(psl->pass##_clip_ps, psl->pass##_ps, st); \ + DRW_PASS_INSTANCE_CREATE( \ + psl->pass##_clip_cull_ps, psl->pass##_cull_ps, st | DRW_STATE_CULL_BACK); \ + DRW_pass_link(psl->pass##_clip_ps, psl->pass##_clip_cull_ps); \ + } while (0) { - DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; - DRW_PASS_CREATE(psl->refract_depth_pass, state); - stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, - psl->refract_depth_pass); - - state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK; - DRW_PASS_CREATE(psl->refract_depth_pass_cull, state); - stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh, - psl->refract_depth_pass_cull); - - state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES; - DRW_PASS_CREATE(psl->refract_depth_pass_clip, state); - stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh, - psl->refract_depth_pass_clip); - - state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES | - DRW_STATE_CULL_BACK; - DRW_PASS_CREATE(psl->refract_depth_pass_clip_cull, state); - stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create( - e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull); - } + DRWState state_depth = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; + DRWState state_shading = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES; + DRWState state_sss = DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS; - { - DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES); - DRW_PASS_CREATE(psl->refract_pass, state); - } + EEVEE_PASS_CREATE(depth, state_depth); + EEVEE_CLIP_PASS_CREATE(depth, state_depth); - { - DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | - DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS); - DRW_PASS_CREATE(psl->sss_pass, state); - DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK); - e_data.sss_count = 0; + EEVEE_PASS_CREATE(depth_refract, state_depth); + EEVEE_CLIP_PASS_CREATE(depth_refract, state_depth); + + EEVEE_PASS_CREATE(material, state_shading); + EEVEE_PASS_CREATE(material_refract, state_shading); + EEVEE_PASS_CREATE(material_sss, state_shading | state_sss); } + { + /* Renderpass accumulation. */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL; + /* Create an instance of each of theses passes and link them together. */ + DRWPass *passes[] = { + psl->material_ps, + psl->material_cull_ps, + psl->material_sss_ps, + psl->material_sss_cull_ps, + }; + DRWPass *first = NULL, *last = NULL; + for (int i = 0; i < ARRAY_SIZE(passes); i++) { + DRWPass *pass = DRW_pass_create_instance("Renderpass Accumulation", passes[i], state); + if (first == NULL) { + first = last = pass; + } + else { + DRW_pass_link(last, pass); + last = pass; + } + } + psl->material_accum_ps = first; + /* Same for background */ + DRW_PASS_INSTANCE_CREATE(psl->background_accum_ps, psl->background_ps, state); + } { DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES; DRW_PASS_CREATE(psl->transparent_pass, state); } - { DRW_PASS_CREATE(psl->update_noise_pass, DRW_STATE_WRITE_COLOR); - DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass); + GPUShader *sh = EEVEE_shaders_update_noise_sh_get(); + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->update_noise_pass); DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex); DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1); DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } +} - if (eevee_hdri_preview_overlay_enabled(draw_ctx->v3d)) { - DRWShadingGroup *shgrp; - - struct GPUBatch *sphere = DRW_cache_sphere_get(); - static float color_chrome[3] = {1.0f, 1.0f, 1.0f}; - static float color_diffuse[3] = {0.8f, 0.8f, 0.8f}; - int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV; +BLI_INLINE void material_shadow(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Material *ma, + bool is_hair, + EeveeMaterialCache *emc) +{ + EEVEE_PrivateData *pd = vedata->stl->g_data; + EEVEE_PassList *psl = vedata->psl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; - if (e_data.default_lit[options] == NULL) { - create_default_shader(options); + if (ma->blend_shadow != MA_BS_NONE) { + /* Shadow Pass */ + const bool use_shadow_shader = ma->use_nodes && ma->nodetree && + ELEM(ma->blend_shadow, MA_BS_CLIP, MA_BS_HASHED); + int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH; + SET_FLAG_FROM_TEST(mat_options, use_shadow_shader, VAR_MAT_HASH); + SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR); + GPUMaterial *gpumat = (use_shadow_shader) ? + EEVEE_material_get(vedata, scene, ma, NULL, mat_options) : + EEVEE_material_default_get(scene, ma, mat_options); + + /* Avoid possible confusion with depth pre-pass options. */ + int option = KEY_SHADOW; + SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR); + + /* Search for the same shaders usage in the pass. */ + struct GPUShader *sh = GPU_material_get_shader(gpumat); + void *cache_key = (char *)sh + option; + DRWShadingGroup *grp, **grp_p; + + if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) { + /* This GPUShader has already been used by another material. + * Add new shading group just after to avoid shader switching cost. */ + grp = DRW_shgroup_create_sub(*grp_p); + } + else { + *grp_p = grp = DRW_shgroup_create(sh, psl->shadow_pass); + EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false); } - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | - DRW_STATE_CULL_BACK; - - DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state); - shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass); - add_standard_uniforms(shgrp, - sldata, - vedata, - NULL, - NULL, - true, - true, - false, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1); - DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f); - DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f); - DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f); - DRW_shgroup_call(shgrp, sphere, NULL); - - DRW_PASS_CREATE(psl->lookdev_glossy_pass, state); - shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass); - add_standard_uniforms(shgrp, - sldata, - vedata, - NULL, - NULL, - true, - true, - false, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1); - DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f); - DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f); - DRW_shgroup_call(shgrp, sphere, NULL); - } + DRW_shgroup_add_material_resources(grp, gpumat); - { - memset(psl->material_accum_pass, 0, sizeof(psl->material_accum_pass)); - for (int pass_index = 0; pass_index < stl->g_data->render_passes_material_count; - pass_index++) { - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL; - DRW_PASS_CREATE(psl->material_accum_pass[pass_index], state); - } + emc->shadow_grp = grp; + emc->shadow_grp_p = grp_p; + } + else { + emc->shadow_grp = NULL; + emc->shadow_grp_p = NULL; } } -#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \ - do { \ - if (oedata) { \ - DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \ - } \ - else { \ - DRW_shgroup_call(shgrp, geom, ob); \ - } \ - } while (0) - -#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \ - do { \ - if (shgrp) { \ - ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \ - } \ - } while (0) - -typedef struct EeveeMaterialShadingGroups { - struct DRWShadingGroup *shading_grp; - struct DRWShadingGroup *depth_grp; - struct DRWShadingGroup *depth_clip_grp; - struct DRWShadingGroup *material_accum_grp[MAX_MATERIAL_RENDER_PASSES]; -} EeveeMaterialShadingGroups; - -static void material_opaque(Material *ma, - GHash *material_hash, - EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - struct GPUMaterial **gpumat, - struct GPUMaterial **gpumat_depth, - struct EeveeMaterialShadingGroups *shgrps, - bool holdout) +static EeveeMaterialCache material_opaque(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Material *ma, + const bool is_hair) { EEVEE_EffectsInfo *effects = vedata->stl->effects; + EEVEE_PrivateData *pd = vedata->stl->g_data; + EEVEE_PassList *psl = vedata->psl; const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; - EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; - bool use_diffuse, use_glossy, use_refract; - bool store_material = true; - float *color_p = &ma->r; - float *metal_p = &ma->metallic; - float *spec_p = &ma->spec; - float *rough_p = &ma->roughness; - const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0; - const bool use_gpumat = (ma->use_nodes && ma->nodetree && !holdout); + const bool do_cull = !is_hair && (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0; + const bool use_gpumat = (ma->use_nodes && ma->nodetree); const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((effects->enabled_effects & EFFECT_REFRACT) != 0); - const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0); + const bool use_depth_shader = use_gpumat && ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED); - EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma); - - if (emsg) { - memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups)); - - /* This will have been created already, just perform a lookup. */ - *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract) : - NULL; - *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get( - scene, ma, (ma->blend_method == MA_BM_HASHED), false) : - NULL; - return; + /* HACK: Assume the struct will never be smaller than our variations. + * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */ + void *key = (char *)ma + is_hair; + /* Search for other material instances (sharing the same Material datablock). */ + EeveeMaterialCache **emc_p, *emc; + if (BLI_ghash_ensure_p(pd->material_hash, key, (void ***)&emc_p)) { + return **emc_p; + } + else { + *emc_p = emc = BLI_memblock_alloc(sldata->material_cache); } - emsg = MEM_callocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups"); - if (use_gpumat) { - static float error_col[3] = {1.0f, 0.0f, 1.0f}; - static float compile_col[3] = {0.5f, 0.5f, 0.5f}; - static float half = 0.5f; - - /* Shading */ - *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract); - - eGPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat); - - /* Alpha CLipped : Discard pixel from depth pass, then - * fail the depth test for shading. */ - if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) { - *gpumat_depth = EEVEE_material_mesh_depth_get( - scene, ma, (ma->blend_method == MA_BM_HASHED), false); + material_shadow(vedata, sldata, ma, is_hair, emc); - eGPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth); - if (status_mat_depth != GPU_MAT_SUCCESS) { - /* Mixing both flags. If depth shader fails, show it to the user by not using - * the surface shader. */ - status_mat_surface = status_mat_depth; - } - else if (use_ssrefract) { - emsg->depth_grp = DRW_shgroup_material_create( - *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); - emsg->depth_clip_grp = DRW_shgroup_material_create( - *gpumat_depth, - (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); - } - else { - emsg->depth_grp = DRW_shgroup_material_create( - *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); - emsg->depth_clip_grp = DRW_shgroup_material_create( - *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); - } - - if (emsg->depth_grp != NULL) { - use_diffuse = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_DIFFUSE); - use_glossy = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_GLOSSY); - use_refract = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_REFRACT); - - add_standard_uniforms(emsg->depth_grp, - sldata, - vedata, - NULL, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - add_standard_uniforms(emsg->depth_clip_grp, - sldata, - vedata, - NULL, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - - if (ma->blend_method == MA_BM_CLIP) { - DRW_shgroup_uniform_float(emsg->depth_grp, "alphaThreshold", &ma->alpha_threshold, 1); - DRW_shgroup_uniform_float( - emsg->depth_clip_grp, "alphaThreshold", &ma->alpha_threshold, 1); - } - } + { + /* Depth Pass */ + int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH; + SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT); + SET_FLAG_FROM_TEST(mat_options, use_depth_shader, VAR_MAT_HASH); + SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR); + GPUMaterial *gpumat = (use_depth_shader) ? + EEVEE_material_get(vedata, scene, ma, NULL, mat_options) : + EEVEE_material_default_get(scene, ma, mat_options); + + int option = 0; + SET_FLAG_FROM_TEST(option, do_cull, KEY_CULL); + SET_FLAG_FROM_TEST(option, use_ssrefract, KEY_REFRACT); + DRWPass *depth_ps = (DRWPass *[]){ + psl->depth_ps, + psl->depth_cull_ps, + psl->depth_refract_ps, + psl->depth_refract_cull_ps, + }[option]; + /* Hair are rendered inside the non-cull pass but needs to have a separate cache key. */ + SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR); + + /* Search for the same shaders usage in the pass. */ + struct GPUShader *sh = GPU_material_get_shader(gpumat); + void *cache_key = (char *)sh + option; + DRWShadingGroup *grp, **grp_p; + + if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) { + /* This GPUShader has already been used by another material. + * Add new shading group just after to avoid shader switching cost. */ + grp = DRW_shgroup_create_sub(*grp_p); } - - switch (status_mat_surface) { - case GPU_MAT_SUCCESS: { - static int no_ssr = 0; - static int first_ssr = 1; - int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ? - &first_ssr : - &no_ssr; - const bool use_sss = GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS); - use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE); - use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY); - use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT); - - emsg->shading_grp = DRW_shgroup_material_create( - *gpumat, - (use_ssrefract) ? - psl->refract_pass : - (use_sss) ? ((do_cull) ? psl->sss_pass_cull : psl->sss_pass) : - ((do_cull) ? psl->material_pass_cull : psl->material_pass)); - - add_standard_uniforms(emsg->shading_grp, - sldata, - vedata, - ssr_id, - &ma->refract_depth, - use_diffuse, - use_glossy, - use_refract, - use_ssrefract, - false, - DEFAULT_RENDER_PASS_FLAG); - - if (use_sss) { - struct GPUTexture *sss_tex_profile = NULL; - struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get( - *gpumat, stl->effects->sss_sample_count, &sss_tex_profile); - - if (sss_profile) { - /* Limit of 8 bit stencil buffer. ID 255 is refraction. */ - if (e_data.sss_count < 254) { - int sss_id = e_data.sss_count + 1; - DRW_shgroup_stencil_mask(emsg->shading_grp, sss_id); - EEVEE_subsurface_add_pass(sldata, vedata, sss_id, sss_profile); - if (use_translucency) { - EEVEE_subsurface_translucency_add_pass( - sldata, vedata, sss_id, sss_profile, sss_tex_profile); - } - e_data.sss_count++; - } - else { - /* TODO : display message. */ - printf("Error: Too many different Subsurface shader in the scene.\n"); - } - } - } - - RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { - emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create( - *gpumat, psl->material_accum_pass[render_pass_index]); - add_standard_uniforms(emsg->material_accum_grp[render_pass_index], - sldata, - vedata, - ssr_id, - &ma->refract_depth, - use_diffuse, - use_glossy, - use_refract, - use_ssrefract, - false, - render_pass_flag); - } - RENDER_PASS_ITER_END(render_pass_index); - - break; - } - case GPU_MAT_QUEUED: { - stl->g_data->queued_shaders_count++; - color_p = compile_col; - metal_p = spec_p = rough_p = ½ - store_material = false; - break; - } - case GPU_MAT_FAILED: - default: - color_p = error_col; - metal_p = spec_p = rough_p = ½ - break; + else { + *grp_p = grp = DRW_shgroup_create(sh, depth_ps); + EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false); } - } - /* Fallback to default shader */ - if (emsg->shading_grp == NULL) { - bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0); - emsg->shading_grp = EEVEE_default_shading_group_get( - sldata, vedata, NULL, NULL, NULL, false, holdout, use_ssr); - DRW_shgroup_uniform_vec3(emsg->shading_grp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(emsg->shading_grp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(emsg->shading_grp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(emsg->shading_grp, "roughness", rough_p, 1); - - RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { - DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get( - sldata, - vedata, - holdout, - use_ssr, - psl->material_accum_pass[render_pass_index], - render_pass_flag); - - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - emsg->material_accum_grp[render_pass_index] = shgrp; - } - RENDER_PASS_ITER_END(render_pass_index); - } + DRW_shgroup_add_material_resources(grp, gpumat); - /* Fallback default depth prepass */ - if (emsg->depth_grp == NULL) { - if (use_ssrefract) { - emsg->depth_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_cull : - stl->g_data->refract_depth_shgrp; - emsg->depth_clip_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull : - stl->g_data->refract_depth_shgrp_clip; + emc->depth_grp = grp; + emc->depth_grp_p = grp_p; + } + { + /* Shading Pass */ + int mat_options = VAR_MAT_MESH; + SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT); + SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR); + GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); + const bool use_sss = GPU_material_flag_get(gpumat, GPU_MATFLAG_SSS); + + int ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ? 1 : 0; + int option = (use_ssrefract ? 0 : (use_sss ? 1 : 2)) * 2 + do_cull; + DRWPass *shading_pass = (DRWPass *[]){ + psl->material_refract_ps, + psl->material_refract_cull_ps, + psl->material_sss_ps, + psl->material_sss_cull_ps, + psl->material_ps, + psl->material_cull_ps, + }[option]; + /* Hair are rendered inside the non-cull pass but needs to have a separate cache key */ + option = option * 2 + is_hair; + + /* Search for the same shaders usage in the pass. */ + /* HACK: Assume the struct will never be smaller than our variations. + * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */ + BLI_assert(option <= 16); + struct GPUShader *sh = GPU_material_get_shader(gpumat); + void *cache_key = (char *)sh + option; + DRWShadingGroup *grp, **grp_p; + + if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) { + /* This GPUShader has already been used by another material. + * Add new shading group just after to avoid shader switching cost. */ + grp = DRW_shgroup_create_sub(*grp_p); } else { - emsg->depth_grp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp; - emsg->depth_clip_grp = (do_cull) ? stl->g_data->depth_shgrp_clip_cull : - stl->g_data->depth_shgrp_clip; + *grp_p = grp = DRW_shgroup_create(sh, shading_pass); + EEVEE_material_bind_resources( + grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, false); } - } + DRW_shgroup_add_material_resources(grp, gpumat); - memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups)); - if (store_material) { - BLI_ghash_insert(material_hash, ma, emsg); - } - else { - MEM_freeN(emsg); + if (use_sss) { + EEVEE_subsurface_add_pass(sldata, vedata, ma, grp, gpumat); + } + + emc->shading_grp = grp; + emc->shading_grp_p = grp_p; + emc->shading_gpumat = gpumat; } + return *emc; } -static void material_transparent(Material *ma, - EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - struct GPUMaterial **gpumat, - struct EeveeMaterialShadingGroups *shgrps) +static EeveeMaterialCache material_transparent(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, + Material *ma) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; - EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = vedata->stl->effects; + EeveeMaterialCache emc = {0}; const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0; const bool use_gpumat = ma->use_nodes && ma->nodetree; const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && - ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0); - const float *color_p = &ma->r; - const float *metal_p = &ma->metallic; - const float *spec_p = &ma->spec; - const float *rough_p = &ma->roughness; - + ((effects->enabled_effects & EFFECT_REFRACT) != 0); const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0); DRWState cur_state; @@ -1677,81 +691,53 @@ static void material_transparent(Material *ma, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_CUSTOM); - /* Depth prepass */ + material_shadow(vedata, sldata, ma, false, &emc); + if (use_prepass) { - shgrps->depth_grp = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); + /* Depth prepass */ + int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH; + GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); + struct GPUShader *sh = GPU_material_get_shader(gpumat); + + DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->transparent_pass); + + EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, true); + DRW_shgroup_add_material_resources(grp, gpumat); cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; - DRW_shgroup_state_disable(shgrps->depth_grp, all_state); - DRW_shgroup_state_enable(shgrps->depth_grp, cur_state); + DRW_shgroup_state_disable(grp, all_state); + DRW_shgroup_state_enable(grp, cur_state); + + emc.depth_grp = grp; } + { + /* Shading */ + int ssr_id = -1; /* TODO transparent SSR */ + int mat_options = VAR_MAT_MESH | VAR_MAT_BLEND; + SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT); + GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); - if (use_gpumat) { - static float error_col[3] = {1.0f, 0.0f, 1.0f}; - static float compile_col[3] = {0.5f, 0.5f, 0.5f}; - static float half = 0.5f; + DRWShadingGroup *grp = DRW_shgroup_create(GPU_material_get_shader(gpumat), + psl->transparent_pass); - /* Shading */ - *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, use_ssrefract); - - switch (GPU_material_status(*gpumat)) { - case GPU_MAT_SUCCESS: { - static int ssr_id = -1; /* TODO transparent SSR */ - - shgrps->shading_grp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); - - bool use_blend = true; - bool use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE); - bool use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY); - bool use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT); - - add_standard_uniforms(shgrps->shading_grp, - sldata, - vedata, - &ssr_id, - &ma->refract_depth, - use_diffuse, - use_glossy, - use_refract, - use_ssrefract, - use_blend, - DEFAULT_RENDER_PASS_FLAG); - break; - } - case GPU_MAT_QUEUED: { - /* TODO Bypass probe compilation. */ - stl->g_data->queued_shaders_count++; - color_p = compile_col; - metal_p = spec_p = rough_p = ½ - break; - } - case GPU_MAT_FAILED: - default: - color_p = error_col; - metal_p = spec_p = rough_p = ½ - break; - } - } + EEVEE_material_bind_resources( + grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, true); + DRW_shgroup_add_material_resources(grp, gpumat); - /* Fallback to default shader */ - if (shgrps->shading_grp == NULL) { - shgrps->shading_grp = EEVEE_default_shading_group_create( - sldata, vedata, psl->transparent_pass, false, true, false); - DRW_shgroup_uniform_vec3(shgrps->shading_grp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrps->shading_grp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrps->shading_grp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrps->shading_grp, "roughness", rough_p, 1); - } + cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM; + cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL; + cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; - cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM; - cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL; - cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; + /* Disable other blend modes and use the one we want. */ + DRW_shgroup_state_disable(grp, all_state); + DRW_shgroup_state_enable(grp, cur_state); - /* Disable other blend modes and use the one we want. */ - DRW_shgroup_state_disable(shgrps->shading_grp, all_state); - DRW_shgroup_state_enable(shgrps->shading_grp, cur_state); + emc.shading_grp = grp; + emc.shading_gpumat = gpumat; + } + return emc; } /* Return correct material or empty default material if slot is empty. */ @@ -1766,12 +752,35 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou ma = BKE_material_default_volume(); } else { - ma = BKE_material_default_empty(); + ma = BKE_material_default_surface(); } } return ma; } +BLI_INLINE EeveeMaterialCache eevee_material_cache_get( + EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, int slot, bool is_hair) +{ + const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; + EeveeMaterialCache matcache; + Material *ma = eevee_object_material_get(ob, slot, holdout); + switch (ma->blend_method) { + case MA_BM_BLEND: + if (!is_hair) { + matcache = material_transparent(vedata, sldata, ma); + break; + } + ATTR_FALLTHROUGH; + case MA_BM_SOLID: + case MA_BM_CLIP: + case MA_BM_HASHED: + default: + matcache = material_opaque(vedata, sldata, ma, is_hair); + break; + } + return matcache; +} + static void eevee_hair_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, @@ -1780,240 +789,49 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata, int matnr, bool *cast_shadow) { - EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; - - DRWShadingGroup *shgrp = NULL; - Material *ma = eevee_object_material_get(ob, matnr - 1, holdout); - const bool use_gpumat = ma->use_nodes && ma->nodetree && !holdout; - const bool use_alpha_hash = (ma->blend_method == MA_BM_HASHED); - const bool use_alpha_clip = (ma->blend_method == MA_BM_CLIP); - const bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0); + EeveeMaterialCache matcache = eevee_material_cache_get(vedata, sldata, ob, matnr - 1, true); - GPUMaterial *gpumat = use_gpumat ? EEVEE_material_hair_get(scene, ma) : NULL; - eGPUMaterialStatus status_mat_surface = gpumat ? GPU_material_status(gpumat) : GPU_MAT_SUCCESS; - - float *color_p = &ma->r; - float *metal_p = &ma->metallic; - float *spec_p = &ma->spec; - float *rough_p = &ma->roughness; - - /* Depth prepass. */ - if (use_gpumat && (use_alpha_clip || use_alpha_hash)) { - GPUMaterial *gpumat_depth = EEVEE_material_hair_depth_get(scene, ma, use_alpha_hash, false); - - eGPUMaterialStatus status_mat_depth = GPU_material_status(gpumat_depth); - - if (status_mat_depth != GPU_MAT_SUCCESS) { - /* Mixing both flags. If depth shader fails, show it to the user by not using - * the surface shader. */ - status_mat_surface = status_mat_depth; - } - else { - const bool use_diffuse = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_DIFFUSE); - const bool use_glossy = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_GLOSSY); - const bool use_refract = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_REFRACT); - - for (int i = 0; i < 2; i++) { - DRWPass *pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip; - - shgrp = DRW_shgroup_material_hair_create(ob, psys, md, pass, gpumat_depth); - - add_standard_uniforms(shgrp, - sldata, - vedata, - NULL, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - - /* Unfortunately needed for correctness but not 99% of the time not needed. - * TODO detect when needed? */ - DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block( - shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); - DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - - if (use_alpha_clip) { - DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1); - } - } - } + if (matcache.depth_grp) { + *matcache.depth_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.depth_grp); } - - /* Fallback to default shader */ - if (shgrp == NULL) { - for (int i = 0; i < 2; i++) { - DRWPass *depth_pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip; - struct GPUShader *depth_sh = (i == 0) ? e_data.default_hair_prepass_sh : - e_data.default_hair_prepass_clip_sh; - DRW_shgroup_hair_create(ob, psys, md, depth_pass, depth_sh); - } + if (matcache.shading_grp) { + *matcache.shading_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shading_grp); } - - shgrp = NULL; - - if (gpumat) { - static int ssr_id; - ssr_id = (use_ssr) ? 1 : -1; - static float half = 0.5f; - static float error_col[3] = {1.0f, 0.0f, 1.0f}; - static float compile_col[3] = {0.5f, 0.5f, 0.5f}; - - switch (status_mat_surface) { - case GPU_MAT_SUCCESS: { - bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE); - bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY); - bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT); - - shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat); - - if (!use_diffuse && !use_glossy && !use_refract) { - /* HACK: Small hack to avoid issue when utilTex is needed for - * world_normals_get and none of the bsdfs are present. - * This binds utilTex even if not needed. */ - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - } - - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - DEFAULT_RENDER_PASS_FLAG); - - /* Add the hair to all the render_passes that are enabled */ - RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { - shgrp = DRW_shgroup_material_hair_create( - ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat); - if (!use_diffuse && !use_glossy && !use_refract) { - /* Small hack to avoid issue when utilTex is needed for - * world_normals_get and none of the bsdfs that need it are present. - * This binds `utilTex` even if not needed. */ - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - } - - add_standard_uniforms(shgrp, - sldata, - vedata, - &ssr_id, - NULL, - use_diffuse, - use_glossy, - use_refract, - false, - false, - render_pass_flag); - } - RENDER_PASS_ITER_END(render_pass_index); - - break; - } - case GPU_MAT_QUEUED: { - stl->g_data->queued_shaders_count++; - color_p = compile_col; - metal_p = spec_p = rough_p = ½ - break; - } - case GPU_MAT_FAILED: - default: - color_p = error_col; - metal_p = spec_p = rough_p = ½ - break; - } + if (matcache.shadow_grp) { + *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp); + *cast_shadow = true; } +} - /* Fallback to default shader */ - if (shgrp == NULL) { - shgrp = EEVEE_default_shading_group_get(sldata, vedata, ob, psys, md, true, holdout, use_ssr); - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - - RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) { - shgrp = EEVEE_default_hair_render_pass_shading_group_get( - sldata, - vedata, - ob, - psys, - md, - holdout, - use_ssr, - psl->material_accum_pass[render_pass_index], - render_pass_flag); - - DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); - DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); - DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); - DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - } - RENDER_PASS_ITER_END(render_pass_index); - } +#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \ + do { \ + if (oedata) { \ + DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \ + } \ + else { \ + DRW_shgroup_call(shgrp, geom, ob); \ + } \ + } while (0) - /* Shadows */ - char blend_shadow = use_gpumat ? ma->blend_shadow : MA_BS_SOLID; - const bool shadow_alpha_hash = (blend_shadow == MA_BS_HASHED); - switch (blend_shadow) { - case MA_BS_SOLID: - DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh); - *cast_shadow = true; - break; - case MA_BS_CLIP: - case MA_BS_HASHED: - gpumat = EEVEE_material_hair_depth_get(scene, ma, shadow_alpha_hash, true); - shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->shadow_pass, gpumat); - /* Unfortunately needed for correctness but not 99% of the time not needed. - * TODO detect when needed? */ - DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block( - shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); - DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - - if (!shadow_alpha_hash) { - DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1); - } - *cast_shadow = true; - break; - case MA_BS_NONE: - default: - break; +#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \ + do { \ + if (shgrp) { \ + ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \ + } \ + } while (0) + +#define MATCACHE_AS_ARRAY(matcache, member, materials_len, output_array) \ + for (int i = 0; i < materials_len; i++) { \ + output_array[i] = matcache[i].member; \ } -} void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, bool *cast_shadow) { - EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - GHash *material_hash = stl->g_data->material_hash; - const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0; bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) && !DRW_state_is_image_render(); @@ -2022,139 +840,64 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { const int materials_len = DRW_cache_object_material_count_get(ob); - struct EeveeMaterialShadingGroups *shgrps_array = BLI_array_alloca(shgrps_array, - materials_len); - - struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); - struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len); - struct Material **ma_array = BLI_array_alloca(ma_array, materials_len); - + EeveeMaterialCache *matcache = BLI_array_alloca(matcache, materials_len); for (int i = 0; i < materials_len; i++) { - ma_array[i] = eevee_object_material_get(ob, i, holdout); - memset(&shgrps_array[i], 0, sizeof(EeveeMaterialShadingGroups)); - gpumat_array[i] = NULL; - gpumat_depth_array[i] = NULL; - - switch (ma_array[i]->blend_method) { - case MA_BM_SOLID: - case MA_BM_CLIP: - case MA_BM_HASHED: - material_opaque(ma_array[i], - material_hash, - sldata, - vedata, - &gpumat_array[i], - &gpumat_depth_array[i], - &shgrps_array[i], - holdout); - break; - case MA_BM_BLEND: - material_transparent(ma_array[i], sldata, vedata, &gpumat_array[i], &shgrps_array[i]); - break; - default: - BLI_assert(0); - break; - } + matcache[i] = eevee_material_cache_get(vedata, sldata, ob, i, false); } /* Only support single volume material for now. */ /* XXX We rely on the previously compiled surface shader * to know if the material has a "volume nodetree". */ - bool use_volume_material = (gpumat_array[0] && - GPU_material_has_volume_output(gpumat_array[0])); + bool use_volume_material = (matcache[0].shading_gpumat && + GPU_material_has_volume_output(matcache[0].shading_gpumat)); if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) { - /* Get per-material split surface */ - struct GPUBatch **mat_geom = NULL; - - if (!use_sculpt_pbvh) { - mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len); - } - if (use_sculpt_pbvh) { - struct DRWShadingGroup **sculpt_shgrps_array = BLI_array_alloca(sculpt_shgrps_array, - materials_len); - for (int i = 0; i < materials_len; i++) { - sculpt_shgrps_array[i] = shgrps_array[i].shading_grp; - } - DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob); + struct DRWShadingGroup **shgrps_array = BLI_array_alloca(shgrps_array, materials_len); - for (int i = 0; i < materials_len; i++) { - sculpt_shgrps_array[i] = shgrps_array[i].depth_grp; - } - DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob); - for (int i = 0; i < materials_len; i++) { - sculpt_shgrps_array[i] = shgrps_array[i].depth_clip_grp; - } - DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob); + MATCACHE_AS_ARRAY(matcache, shading_grp, materials_len, shgrps_array); + DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob); - for (int renderpass_index = 0; - renderpass_index < stl->g_data->render_passes_material_count; - renderpass_index++) { - for (int i = 0; i < materials_len; i++) { - sculpt_shgrps_array[i] = shgrps_array[i].material_accum_grp[renderpass_index]; - } - DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob); - } + MATCACHE_AS_ARRAY(matcache, depth_grp, materials_len, shgrps_array); + DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob); - /* TODO(fclem): Support shadows in sculpt mode. */ + MATCACHE_AS_ARRAY(matcache, shadow_grp, materials_len, shgrps_array); + DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob); } - else if (mat_geom) { - for (int i = 0; i < materials_len; i++) { - if (mat_geom[i] == NULL) { - continue; - } + else { + struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); + MATCACHE_AS_ARRAY(matcache, shading_gpumat, materials_len, gpumat_array); + /* Get per-material split surface */ + struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len); - /* Do not render surface if we are rendering a volume object - * and do not have a surface closure. */ - if (use_volume_material && - (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) { - continue; - } + if (mat_geom) { + for (int i = 0; i < materials_len; i++) { + if (mat_geom[i] == NULL) { + continue; + } - /* XXX TODO rewrite this to include the dupli objects. - * This means we cannot exclude dupli objects from reflections!!! */ - EEVEE_ObjectEngineData *oedata = NULL; - if ((ob->base_flag & BASE_FROM_DUPLI) == 0) { - oedata = EEVEE_object_data_ensure(ob); - oedata->ob = ob; - oedata->test_data = &sldata->probes->vis_data; - } - EeveeMaterialShadingGroups *shgrps = &shgrps_array[i]; - ADD_SHGROUP_CALL(shgrps->shading_grp, ob, mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrps->depth_grp, ob, mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrps->depth_clip_grp, ob, mat_geom[i], oedata); - for (int renderpass_index = 0; - renderpass_index < stl->g_data->render_passes_material_count; - renderpass_index++) { - ADD_SHGROUP_CALL_SAFE( - shgrps->material_accum_grp[renderpass_index], ob, mat_geom[i], oedata); - } + /* Do not render surface if we are rendering a volume object + * and do not have a surface closure. */ + if (use_volume_material && + (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) { + continue; + } + + /* XXX TODO rewrite this to include the dupli objects. + * This means we cannot exclude dupli objects from reflections!!! */ + EEVEE_ObjectEngineData *oedata = NULL; + if ((ob->base_flag & BASE_FROM_DUPLI) == 0) { + oedata = EEVEE_object_data_ensure(ob); + oedata->ob = ob; + oedata->test_data = &sldata->probes->vis_data; + } - /* Shadow Pass */ - struct GPUMaterial *gpumat; - const bool use_gpumat = (ma_array[i]->use_nodes && ma_array[i]->nodetree); - char blend_shadow = use_gpumat ? ma_array[i]->blend_shadow : MA_BS_SOLID; - switch (blend_shadow) { - case MA_BS_SOLID: - EEVEE_shadows_caster_add(sldata, stl, mat_geom[i], ob); - *cast_shadow = true; - break; - case MA_BS_CLIP: - gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true); - EEVEE_shadows_caster_material_add( - sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold); - *cast_shadow = true; - break; - case MA_BS_HASHED: - gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true); - EEVEE_shadows_caster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL); - *cast_shadow = true; - break; - case MA_BS_NONE: - default: - break; + ADD_SHGROUP_CALL(matcache[i].shading_grp, ob, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(matcache[i].depth_grp, ob, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(matcache[i].shadow_grp, ob, mat_geom[i], oedata); + *cast_shadow = (matcache[i].shadow_grp != NULL); } } } @@ -2205,11 +948,12 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata, void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { - EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_PrivateData *pd = vedata->stl->g_data; + EEVEE_EffectsInfo *effects = vedata->stl->effects; - BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN); + BLI_ghash_free(pd->material_hash, NULL, NULL); - SET_FLAG_FROM_TEST(stl->effects->enabled_effects, e_data.sss_count > 0, EFFECT_SSS); + SET_FLAG_FROM_TEST(effects->enabled_effects, effects->sss_surface_count > 0, EFFECT_SSS); /* TODO(fclem) this is not really clean. Init should not be done in cache finish. */ EEVEE_subsurface_draw_init(sldata, vedata); @@ -2217,38 +961,10 @@ void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat void EEVEE_materials_free(void) { - for (int i = 0; i < VAR_MAT_MAX; i++) { - DRW_SHADER_FREE_SAFE(e_data.default_lit[i]); - } - MEM_SAFE_FREE(e_data.frag_shader_lib); - MEM_SAFE_FREE(e_data.vert_shader_str); - MEM_SAFE_FREE(e_data.vert_shadow_shader_str); - MEM_SAFE_FREE(e_data.vert_background_shader_str); - MEM_SAFE_FREE(e_data.vert_volume_shader_str); - MEM_SAFE_FREE(e_data.geom_volume_shader_str); - MEM_SAFE_FREE(e_data.volume_shader_lib); - DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh); - DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh); - DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh); - DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh); - DRW_SHADER_FREE_SAFE(e_data.default_background); - DRW_SHADER_FREE_SAFE(e_data.update_noise_sh); DRW_TEXTURE_FREE_SAFE(e_data.util_tex); DRW_TEXTURE_FREE_SAFE(e_data.noise_tex); } -void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl) -{ - for (int i = 0; i < VAR_MAT_MAX; i++) { - if (psl->default_pass[i]) { - DRW_draw_pass(psl->default_pass[i]); - } - } - - DRW_draw_pass(psl->material_pass); - DRW_draw_pass(psl->material_pass_cull); -} - /* -------------------------------------------------------------------- */ /** \name Render Passes @@ -2256,172 +972,140 @@ void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Pass void EEVEE_material_renderpasses_init(EEVEE_Data *vedata) { - EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; + EEVEE_PrivateData *pd = vedata->stl->g_data; /* For diffuse and glossy we calculate the final light + color buffer where we extract the * light from by dividing by the color buffer. When one the light is requested we also tag * the color buffer to do the extraction. */ - if (g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { - g_data->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR; + if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { + pd->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR; } - if (g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { - g_data->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR; + if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { + pd->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR; } +} - /* Calculate the number of material based render passes */ - uint num_render_passes = count_bits_i(stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL); - if ((num_render_passes != 0 && stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) == - 0) { - num_render_passes += 1; +static void material_renderpass_init(EEVEE_FramebufferList *fbl, + GPUTexture **output_tx, + const eGPUTextureFormat format, + const bool do_clear) +{ + DRW_texture_ensure_fullscreen_2d(output_tx, format, 0); + /* Clear texture. */ + if (do_clear) { + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + /* TODO(fclem) replace by GPU_texture_clear once it is fast. */ + GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0); + GPU_framebuffer_bind(fbl->material_accum_fb); + GPU_framebuffer_clear_color(fbl->material_accum_fb, clear); + GPU_framebuffer_bind(fbl->main_fb); + GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx); } - stl->g_data->render_passes_material_count = num_render_passes; } void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) { - const DRWContextState *draw_ctx = DRW_context_state_get(); EEVEE_FramebufferList *fbl = vedata->fbl; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); EEVEE_TextureList *txl = vedata->txl; EEVEE_StorageList *stl = vedata->stl; - EEVEE_PassList *psl = vedata->psl; EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_PrivateData *pd = stl->g_data; - float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + /* Should be enough precision for many samples. */ + const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; + const bool do_clear = DRW_state_is_image_render() || (effects->taa_current_sample == 1); /* Create FrameBuffer. */ + GPU_framebuffer_ensure_config(&fbl->material_accum_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE}); - /* Should be enough precision for many samples. */ - const eGPUTextureFormat texture_format_material_accum = (tot_samples > 128) ? GPU_RGBA32F : - GPU_RGBA16F; - const eViewLayerEEVEEPassType render_passes = stl->g_data->render_passes & - EEVEE_RENDERPASSES_MATERIAL; - if (render_passes != 0) { - GPU_framebuffer_ensure_config(&fbl->material_accum_fb, - {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE}); - int render_pass_index = ((render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) != 0) ? 0 : 1; - for (int bit = 0; bit < 32; bit++) { - eViewLayerEEVEEPassType bitflag = (1 << bit); - if ((render_passes & bitflag) != 0) { - - DRW_texture_ensure_fullscreen_2d( - &txl->material_accum[render_pass_index], texture_format_material_accum, 0); - - /* Clear texture. */ - if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { - GPU_framebuffer_texture_attach( - fbl->material_accum_fb, txl->material_accum[render_pass_index], 0, 0); - GPU_framebuffer_bind(fbl->material_accum_fb); - GPU_framebuffer_clear_color(fbl->material_accum_fb, clear); - GPU_framebuffer_bind(fbl->main_fb); - GPU_framebuffer_texture_detach(fbl->material_accum_fb, - txl->material_accum[render_pass_index]); - } - render_pass_index++; - } - } + if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { + material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear); + } + if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) { + material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear); + } + if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) { + material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear); + } + if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { + material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear); + } + if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) { + material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear); + } + if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { + material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear); - if ((render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) && - (effects->enabled_effects & EFFECT_SSR)) { + if (effects->enabled_effects & EFFECT_SSR) { EEVEE_reflection_output_init(sldata, vedata, tot_samples); } + } +} - if (render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { - Scene *scene = draw_ctx->scene; - World *wo = scene->world; +static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl, + DRWPass *renderpass, + EEVEE_PrivateData *pd, + GPUTexture *output_tx, + struct GPUUniformBuffer *renderpass_option_ubo) +{ + GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0); + GPU_framebuffer_bind(fbl->material_accum_fb); - if (wo && wo->use_nodes && wo->nodetree) { - struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo); - if (GPU_material_status(gpumat) == GPU_MAT_SUCCESS) { - DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->material_accum_pass[0]); - add_background_uniforms(grp, sldata, vedata); - DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); - } - } - } - } + pd->renderpass_ubo = renderpass_option_ubo; + DRW_draw_pass(renderpass); + + GPU_framebuffer_texture_detach(fbl->material_accum_fb, output_tx); } void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *pd = vedata->stl->g_data; + EEVEE_EffectsInfo *effects = vedata->stl->effects; EEVEE_TextureList *txl = vedata->txl; if (fbl->material_accum_fb != NULL) { - for (int renderpass_index = 0; renderpass_index < stl->g_data->render_passes_material_count; - renderpass_index++) { - if (txl->material_accum[renderpass_index] != NULL) { - GPU_framebuffer_texture_attach( - fbl->material_accum_fb, txl->material_accum[renderpass_index], 0, 0); - GPU_framebuffer_bind(fbl->material_accum_fb); - DRW_draw_pass(psl->material_accum_pass[renderpass_index]); - GPU_framebuffer_bind(fbl->main_fb); - GPU_framebuffer_texture_detach(fbl->material_accum_fb, - txl->material_accum[renderpass_index]); - } + DRWPass *material_accum_ps = psl->material_accum_ps; + if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { + material_renderpass_accumulate( + fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.combined); } - if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) && - (stl->effects->enabled_effects & EFFECT_SSR)) { - EEVEE_reflection_output_accumulate(sldata, vedata); + if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) { + material_renderpass_accumulate( + fbl, material_accum_ps, pd, txl->emit_accum, sldata->renderpass_ubo.emit); } - } -} - -int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata), - EEVEE_Data *vedata, - eViewLayerEEVEEPassType renderpass_type) -{ - EEVEE_StorageList *stl = vedata->stl; - - BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL) != 0); - BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL & renderpass_type) != 0); - - /* pass_index 0 is reserved for the environment pass. */ - if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT & renderpass_type) != 0) { - return 0; - } - - /* pass_index 0 is reserved for the environment pass. Other passes start from index 1 */ - int index = 1; - eViewLayerEEVEEPassType active_material_passes = stl->g_data->render_passes & - EEVEE_RENDERPASSES_MATERIAL & - ~EEVEE_RENDER_PASS_ENVIRONMENT; + if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) { + material_renderpass_accumulate( + fbl, material_accum_ps, pd, txl->diff_color_accum, sldata->renderpass_ubo.diff_color); + } + if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) { + material_renderpass_accumulate( + fbl, material_accum_ps, pd, txl->diff_light_accum, sldata->renderpass_ubo.diff_light); - for (int bitshift = 0; bitshift < 32; bitshift++) { - eViewLayerEEVEEPassType pass_flag = (1 << bitshift); - if (pass_flag == renderpass_type) { - break; + if (effects->enabled_effects & EFFECT_SSS) { + EEVEE_subsurface_output_accumulate(sldata, vedata); + } } - if (active_material_passes & pass_flag) { - index++; + if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) { + material_renderpass_accumulate( + fbl, material_accum_ps, pd, txl->spec_color_accum, sldata->renderpass_ubo.spec_color); } - } + if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { + material_renderpass_accumulate( + fbl, material_accum_ps, pd, txl->spec_light_accum, sldata->renderpass_ubo.spec_light); - return index; -} + if (effects->enabled_effects & EFFECT_SSR) { + EEVEE_reflection_output_accumulate(sldata, vedata); + } + } -/* Get the pass index that contains the color pass for the given renderpass_type. */ -int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - eViewLayerEEVEEPassType renderpass_type) -{ - BLI_assert( - ELEM(renderpass_type, EEVEE_RENDER_PASS_DIFFUSE_LIGHT, EEVEE_RENDER_PASS_SPECULAR_LIGHT)); - eViewLayerEEVEEPassType color_pass_type; - switch (renderpass_type) { - case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: - color_pass_type = EEVEE_RENDER_PASS_DIFFUSE_COLOR; - break; - case EEVEE_RENDER_PASS_SPECULAR_LIGHT: - color_pass_type = EEVEE_RENDER_PASS_SPECULAR_COLOR; - break; - default: - color_pass_type = 0; - BLI_assert(false); + /* Restore default. */ + pd->renderpass_ubo = sldata->renderpass_ubo.combined; + GPU_framebuffer_bind(fbl->main_fb); } - return EEVEE_material_output_pass_index_get(sldata, vedata, color_pass_type); } + /* \} */ diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index cdcfd64d995..7b942784ee9 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -114,8 +114,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1); DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index be4dfd07ce1..f5ebbe08dd1 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -170,8 +170,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } else { @@ -209,8 +208,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call(grp, quad, NULL); DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR); @@ -219,8 +217,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer); DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1); DRW_shgroup_call(grp, quad, NULL); @@ -233,8 +230,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input); DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call(grp, quad, NULL); } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 264f301e52c..dbe2adef789 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -158,35 +158,34 @@ BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d) (EEVEE_RENDER_PASS_EMIT | EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_DIFFUSE_LIGHT | \ EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_SPECULAR_LIGHT | \ EEVEE_RENDER_PASS_ENVIRONMENT) -#define MAX_MATERIAL_RENDER_PASSES 6 -#define MAX_MATERIAL_RENDER_PASSES_UBO 6 -/* World shader variations */ -enum { - VAR_WORLD_BACKGROUND = 0, - VAR_WORLD_PROBE = 1, - VAR_WORLD_VOLUME = 2, -}; /* Material shader variations */ enum { VAR_MAT_MESH = (1 << 0), - VAR_MAT_PROBE = (1 << 1), + VAR_MAT_VOLUME = (1 << 1), VAR_MAT_HAIR = (1 << 2), - VAR_MAT_BLEND = (1 << 3), - VAR_MAT_VOLUME = (1 << 4), + VAR_MAT_PROBE = (1 << 3), + VAR_MAT_BLEND = (1 << 4), VAR_MAT_LOOKDEV = (1 << 5), VAR_MAT_HOLDOUT = (1 << 6), - /* Max number of variation */ - /* IMPORTANT : Leave it last and set - * it's value accordingly. */ - VAR_MAT_MAX = (1 << 7), - /* These are options that are not counted in VAR_MAT_MAX - * because they are not cumulative with the others above. */ - VAR_MAT_CLIP = (1 << 9), - VAR_MAT_HASH = (1 << 10), - VAR_MAT_MULT = (1 << 11), - VAR_MAT_SHADOW = (1 << 12), - VAR_MAT_REFRACT = (1 << 13), + VAR_MAT_HASH = (1 << 7), + VAR_MAT_DEPTH = (1 << 8), + VAR_MAT_REFRACT = (1 << 9), + VAR_WORLD_BACKGROUND = (1 << 10), + VAR_WORLD_PROBE = (1 << 11), + VAR_WORLD_VOLUME = (1 << 12), + VAR_DEFAULT = (1 << 13), +}; + +/* Material shader cache keys */ +enum { + /* HACK: This assumes the struct GPUShader will never be smaller than our variations. + * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. + * We combine the GPUShader pointer with the key. */ + KEY_CULL = (1 << 0), + KEY_REFRACT = (1 << 1), + KEY_HAIR = (1 << 2), + KEY_SHADOW = (1 << 3), }; /* ************ PROBE UBO ************* */ @@ -272,23 +271,26 @@ typedef struct EEVEE_PassList { struct DRWPass *maxz_copydepth_ps; struct DRWPass *maxz_copydepth_layer_ps; - struct DRWPass *depth_pass; - struct DRWPass *depth_pass_cull; - struct DRWPass *depth_pass_clip; - struct DRWPass *depth_pass_clip_cull; - struct DRWPass *refract_depth_pass; - struct DRWPass *refract_depth_pass_cull; - struct DRWPass *refract_depth_pass_clip; - struct DRWPass *refract_depth_pass_clip_cull; - struct DRWPass *default_pass[VAR_MAT_MAX]; - struct DRWPass *sss_pass; - struct DRWPass *sss_pass_cull; - struct DRWPass *material_pass; - struct DRWPass *material_pass_cull; - struct DRWPass *material_accum_pass[MAX_MATERIAL_RENDER_PASSES]; - struct DRWPass *refract_pass; + /* Renderpass Accumulation. */ + struct DRWPass *material_accum_ps; + struct DRWPass *background_accum_ps; + + struct DRWPass *depth_ps; + struct DRWPass *depth_cull_ps; + struct DRWPass *depth_clip_ps; + struct DRWPass *depth_clip_cull_ps; + struct DRWPass *depth_refract_ps; + struct DRWPass *depth_refract_cull_ps; + struct DRWPass *depth_refract_clip_ps; + struct DRWPass *depth_refract_clip_cull_ps; + struct DRWPass *material_ps; + struct DRWPass *material_cull_ps; + struct DRWPass *material_refract_ps; + struct DRWPass *material_refract_cull_ps; + struct DRWPass *material_sss_ps; + struct DRWPass *material_sss_cull_ps; struct DRWPass *transparent_pass; - struct DRWPass *background_pass; + struct DRWPass *background_ps; struct DRWPass *update_noise_pass; struct DRWPass *lookdev_glossy_pass; struct DRWPass *lookdev_diffuse_pass; @@ -348,7 +350,12 @@ typedef struct EEVEE_TextureList { struct GPUTexture *mist_accum; struct GPUTexture *ao_accum; struct GPUTexture *sss_accum; - struct GPUTexture *material_accum[MAX_MATERIAL_RENDER_PASSES]; + struct GPUTexture *env_accum; + struct GPUTexture *diff_color_accum; + struct GPUTexture *diff_light_accum; + struct GPUTexture *spec_color_accum; + struct GPUTexture *spec_light_accum; + struct GPUTexture *emit_accum; struct GPUTexture *bloom_accum; struct GPUTexture *ssr_accum; struct GPUTexture *shadow_accum; @@ -574,6 +581,7 @@ typedef struct EEVEE_EffectsInfo { bool swap_double_buffer; /* SSSS */ int sss_sample_count; + int sss_surface_count; struct GPUTexture *sss_irradiance; /* Textures from pool */ struct GPUTexture *sss_radius; struct GPUTexture *sss_albedo; @@ -754,14 +762,22 @@ typedef struct EEVEE_ViewLayerData { struct GPUUniformBuffer *planar_ubo; /* Material Render passes */ - struct EEVEE_RenderPassData renderpass_data[MAX_MATERIAL_RENDER_PASSES_UBO]; - struct GPUUniformBuffer *renderpass_ubo[MAX_MATERIAL_RENDER_PASSES_UBO]; + struct { + struct GPUUniformBuffer *combined; + struct GPUUniformBuffer *diff_color; + struct GPUUniformBuffer *diff_light; + struct GPUUniformBuffer *spec_color; + struct GPUUniformBuffer *spec_light; + struct GPUUniformBuffer *emit; + } renderpass_ubo; /* Common Uniform Buffer */ struct EEVEE_CommonUniformBuffer common_data; struct GPUUniformBuffer *common_ubo; struct LightCache *fallback_lightcache; + + struct BLI_memblock *material_cache; } EEVEE_ViewLayerData; /* ************ OBJECT DATA ************ */ @@ -809,14 +825,6 @@ typedef struct EEVEE_Data { typedef struct EEVEE_PrivateData { struct DRWShadingGroup *shadow_shgrp; struct DRWShadingGroup *shadow_accum_shgrp; - struct DRWShadingGroup *depth_shgrp; - struct DRWShadingGroup *depth_shgrp_cull; - struct DRWShadingGroup *depth_shgrp_clip; - struct DRWShadingGroup *depth_shgrp_clip_cull; - struct DRWShadingGroup *refract_depth_shgrp; - struct DRWShadingGroup *refract_depth_shgrp_cull; - struct DRWShadingGroup *refract_depth_shgrp_clip; - struct DRWShadingGroup *refract_depth_shgrp_clip_cull; struct DRWCallBuffer *planar_display_shgrp; struct GHash *material_hash; float background_alpha; /* TODO find a better place for this. */ @@ -862,9 +870,8 @@ typedef struct EEVEE_PrivateData { GPUTexture *renderpass_input; GPUTexture *renderpass_col_input; GPUTexture *renderpass_light_input; - /* The number of active material based render passes */ - uint render_passes_material_count; - + /* Renderpass ubo reference used by material pass. */ + struct GPUUniformBuffer *renderpass_ubo; /** For rendering shadows. */ struct DRWView *cube_views[6]; /** For rendering probes. */ @@ -892,6 +899,7 @@ EEVEE_WorldEngineData *EEVEE_world_data_ensure(World *wo); /* eevee_materials.c */ struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl); void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); @@ -908,31 +916,20 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata, Object *ob, bool *cast_shadow); void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo); -struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo); -struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo); -struct GPUMaterial *EEVEE_material_mesh_get( - struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_refract); -struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma); -struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, - Material *ma, - bool use_hashed_alpha, - bool is_shadow); -struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma); -struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata); void EEVEE_materials_free(void); -void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl); void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]); void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]); void EEVEE_material_renderpasses_init(EEVEE_Data *vedata); void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata), - EEVEE_Data *vedata, - eViewLayerEEVEEPassType renderpass_type); -int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - eViewLayerEEVEEPassType renderpass_type); +void EEVEE_material_bind_resources(DRWShadingGroup *shgrp, + struct GPUMaterial *gpumat, + EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + int *ssr_id, + float *refract_depth, + bool use_ssrefraction, + bool use_alpha_blend); /* eevee_lights.c */ void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]); void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); @@ -943,16 +940,6 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh); void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata); void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *sldata, - EEVEE_StorageList *stl, - struct GPUBatch *geom, - Object *ob); -void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata, - EEVEE_PassList *psl, - struct GPUMaterial *gpumat, - struct GPUBatch *geom, - struct Object *ob, - const float *alpha_threshold); void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, struct Object *ob); void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob); @@ -986,6 +973,7 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]); /* eevee_shaders.c */ void EEVEE_shaders_lightprobe_shaders_init(void); +void EEVEE_shaders_material_shaders_init(void); struct GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void); struct GPUShader *EEVEE_shaders_probe_default_sh_get(void); struct GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void); @@ -993,12 +981,22 @@ struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void); struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void); struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void); struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void); +struct GPUShader *EEVEE_shaders_default_background_sh_get(void); struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void); struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void); struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void); struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void); +struct GPUShader *EEVEE_shaders_update_noise_sh_get(void); struct GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void); struct GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects); +struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma); +struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo); +Material *EEVEE_material_default_diffuse_get(void); +Material *EEVEE_material_default_glossy_get(void); +Material *EEVEE_material_default_error_get(void); +struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options); +struct GPUMaterial *EEVEE_material_get( + EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options); void EEVEE_shaders_free(void); /* eevee_lightprobes.c */ @@ -1105,13 +1103,9 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, uint tot_samples); void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - uint sss_id, - struct GPUUniformBuffer *sss_profile); -void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - uint sss_id, - struct GPUUniformBuffer *sss_profile, - struct GPUTexture *sss_tex_profile); + Material *ma, + DRWShadingGroup *shgrp, + struct GPUMaterial *gpumat); void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 076738dcbdf..89a5ad2198a 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -151,7 +151,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * * `EEVEE_effects_init` needs to go second for TAA. */ EEVEE_renderpasses_init(vedata); EEVEE_effects_init(sldata, vedata, ob_camera_eval, false); - EEVEE_materials_init(sldata, stl, fbl); + EEVEE_materials_init(sldata, vedata, stl, fbl); EEVEE_shadows_init(sldata); EEVEE_lightprobes_init(sldata, vedata); @@ -463,7 +463,7 @@ static void eevee_render_draw_background(EEVEE_Data *vedata) GPU_ATTACHMENT_NONE}); GPU_framebuffer_bind(fbl->main_fb); - DRW_draw_pass(psl->background_pass); + DRW_draw_pass(psl->background_ps); GPU_framebuffer_ensure_config(&fbl->main_fb, {GPU_ATTACHMENT_LEAVE, @@ -556,7 +556,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl EEVEE_update_noise(psl, fbl, r); EEVEE_temporal_sampling_matrices_calc(stl->effects, r); EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1); - EEVEE_materials_init(sldata, stl, fbl); + EEVEE_materials_init(sldata, vedata, stl, fbl); /* Refresh Probes * Shadows needs to be updated for correct probes */ @@ -578,8 +578,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl GPU_framebuffer_bind(fbl->main_fb); GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil); /* Depth prepass */ - DRW_draw_pass(psl->depth_pass); - DRW_draw_pass(psl->depth_pass_cull); + DRW_draw_pass(psl->depth_ps); /* Create minmax texture */ EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); @@ -587,16 +586,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl /* Shading pass */ eevee_render_draw_background(vedata); GPU_framebuffer_bind(fbl->main_fb); - EEVEE_materials_draw_opaque(sldata, psl); + DRW_draw_pass(psl->material_ps); EEVEE_subsurface_data_render(sldata, vedata); /* Effects pre-transparency */ EEVEE_subsurface_compute(sldata, vedata); EEVEE_reflection_compute(sldata, vedata); EEVEE_refraction_compute(sldata, vedata); /* Opaque refraction */ - DRW_draw_pass(psl->refract_depth_pass); - DRW_draw_pass(psl->refract_depth_pass_cull); - DRW_draw_pass(psl->refract_pass); + DRW_draw_pass(psl->depth_refract_ps); + DRW_draw_pass(psl->material_refract_ps); /* Result NORMAL */ eevee_render_result_normal(rl, viewname, rect, vedata, sldata); /* Volumetrics Resolve Opaque */ diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 9112e14dcf5..4a1880caf7d 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -201,8 +201,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, grp, "inputSecondLightBuffer", &g_data->renderpass_light_input); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_uniform_int(grp, "currentSample", &g_data->renderpass_current_sample, 1); DRW_shgroup_uniform_int(grp, "renderpassType", &g_data->renderpass_type, 1); DRW_shgroup_uniform_int(grp, "postProcessType", &g_data->renderpass_postprocess, 1); @@ -225,7 +224,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, * Only invoke this function for passes that need post-processing. * * After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */ -void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, eViewLayerEEVEEPassType renderpass_type) { @@ -276,22 +275,30 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, g_data->renderpass_input = txl->shadow_accum; break; } - case EEVEE_RENDER_PASS_DIFFUSE_COLOR: - case EEVEE_RENDER_PASS_SPECULAR_COLOR: - case EEVEE_RENDER_PASS_ENVIRONMENT: + case EEVEE_RENDER_PASS_DIFFUSE_COLOR: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->diff_color_accum; + break; + } + case EEVEE_RENDER_PASS_SPECULAR_COLOR: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->spec_color_accum; + break; + } + case EEVEE_RENDER_PASS_ENVIRONMENT: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->env_accum; + break; + } case EEVEE_RENDER_PASS_EMIT: { g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; - int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type); - g_data->renderpass_input = txl->material_accum[renderpass_index]; + g_data->renderpass_input = txl->emit_accum; break; } case EEVEE_RENDER_PASS_SPECULAR_LIGHT: { g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; - int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type); - int renderpass_index_color = EEVEE_material_output_color_pass_index_get( - sldata, vedata, renderpass_type); - g_data->renderpass_input = txl->material_accum[renderpass_index]; - g_data->renderpass_col_input = txl->material_accum[renderpass_index_color]; + g_data->renderpass_input = txl->spec_light_accum; + g_data->renderpass_col_input = txl->spec_color_accum; if ((stl->effects->enabled_effects & EFFECT_SSR) != 0) { g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS; g_data->renderpass_light_input = txl->ssr_accum; @@ -303,11 +310,8 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, } case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: { g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; - int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type); - int renderpass_index_color = EEVEE_material_output_color_pass_index_get( - sldata, vedata, renderpass_type); - g_data->renderpass_input = txl->material_accum[renderpass_index]; - g_data->renderpass_col_input = txl->material_accum[renderpass_index_color]; + g_data->renderpass_input = txl->diff_light_accum; + g_data->renderpass_col_input = txl->diff_color_accum; if ((stl->effects->enabled_effects & EFFECT_SSS) != 0) { g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS; g_data->renderpass_light_input = txl->sss_accum; @@ -343,10 +347,6 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, if ((render_pass & EEVEE_RENDER_PASS_MIST) != 0) { EEVEE_mist_output_accumulate(sldata, vedata); } - if ((render_pass & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0 && - (effects->enabled_effects & EFFECT_SSS) != 0) { - EEVEE_subsurface_output_accumulate(sldata, vedata); - } if ((render_pass & EEVEE_RENDER_PASS_AO) != 0) { EEVEE_occlusion_output_accumulate(sldata, vedata); } diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 2e467fe8535..cece67334c5 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -237,8 +237,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); if (!effects->reflection_trace_full) { DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1); } @@ -259,8 +258,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1); if ((effects->enabled_effects & EFFECT_GTAO) != 0) { DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index 50b7c5c5f97..4d25f62a317 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -22,12 +22,20 @@ #include "DRW_render.h" +#include "BKE_lib_id.h" +#include "BKE_node.h" + +#include "BLI_dynstr.h" #include "BLI_string_utils.h" #include "MEM_guardedalloc.h" +#include "GPU_material.h" #include "GPU_shader.h" +#include "NOD_shader.h" + +#include "eevee_engine.h" #include "eevee_private.h" static const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n" @@ -61,6 +69,38 @@ static struct { struct GPUShader *taa_resolve_sh; struct GPUShader *taa_resolve_reproject_sh; + /* General purpose Shaders. */ + struct GPUShader *default_background; + struct GPUShader *update_noise_sh; + + /* Shader strings */ + char *frag_shader_lib; + char *vert_shader_str; + char *vert_shadow_shader_str; + char *vert_background_shader_str; + char *vert_volume_shader_str; + char *geom_volume_shader_str; + char *volume_shader_lib; + + /* LookDev Materials */ + Material *glossy_mat; + Material *diffuse_mat; + + Material *error_mat; + + /* Default Material */ + struct { + bNodeTree *ntree; + bNodeSocketValueRGBA *color_socket; + bNodeSocketValueFloat *metallic_socket; + bNodeSocketValueFloat *roughness_socket; + bNodeSocketValueFloat *specular_socket; + } surface; + + struct { + bNodeTree *ntree; + bNodeSocketValueRGBA *color_socket; + } world; } e_data = {NULL}; /* Engine data */ extern char datatoc_bsdf_common_lib_glsl[]; @@ -68,27 +108,42 @@ extern char datatoc_bsdf_sampling_lib_glsl[]; extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_ambient_occlusion_lib_glsl[]; extern char datatoc_background_vert_glsl[]; +extern char datatoc_common_hair_lib_glsl[]; +extern char datatoc_cubemap_lib_glsl[]; extern char datatoc_default_world_frag_glsl[]; -extern char datatoc_lightprobe_geom_glsl[]; -extern char datatoc_lightprobe_vert_glsl[]; +extern char datatoc_irradiance_lib_glsl[]; extern char datatoc_lightprobe_cube_display_frag_glsl[]; extern char datatoc_lightprobe_cube_display_vert_glsl[]; extern char datatoc_lightprobe_filter_diffuse_frag_glsl[]; extern char datatoc_lightprobe_filter_glossy_frag_glsl[]; extern char datatoc_lightprobe_filter_visibility_frag_glsl[]; +extern char datatoc_lightprobe_geom_glsl[]; extern char datatoc_lightprobe_grid_display_frag_glsl[]; extern char datatoc_lightprobe_grid_display_vert_glsl[]; extern char datatoc_lightprobe_grid_fill_frag_glsl[]; +extern char datatoc_lightprobe_lib_glsl[]; extern char datatoc_lightprobe_planar_display_frag_glsl[]; extern char datatoc_lightprobe_planar_display_vert_glsl[]; extern char datatoc_lightprobe_planar_downsample_frag_glsl[]; extern char datatoc_lightprobe_planar_downsample_geom_glsl[]; extern char datatoc_lightprobe_planar_downsample_vert_glsl[]; -extern char datatoc_irradiance_lib_glsl[]; -extern char datatoc_lightprobe_lib_glsl[]; +extern char datatoc_lightprobe_vert_glsl[]; +extern char datatoc_lights_lib_glsl[]; +extern char datatoc_lit_surface_frag_glsl[]; +extern char datatoc_lit_surface_vert_glsl[]; +extern char datatoc_ltc_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; -extern char datatoc_cubemap_lib_glsl[]; +extern char datatoc_prepass_frag_glsl[]; +extern char datatoc_raytrace_lib_glsl[]; +extern char datatoc_shadow_vert_glsl[]; +extern char datatoc_ssr_lib_glsl[]; +extern char datatoc_update_noise_frag_glsl[]; +extern char datatoc_volumetric_frag_glsl[]; +extern char datatoc_volumetric_geom_glsl[]; +extern char datatoc_volumetric_lib_glsl[]; +extern char datatoc_volumetric_vert_glsl[]; /* Velocity Resolve */ extern char datatoc_effect_velocity_resolve_frag_glsl[]; @@ -150,6 +205,64 @@ void EEVEE_shaders_lightprobe_shaders_init(void) NULL); } +void EEVEE_shaders_material_shaders_init(void) +{ + e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_raytrace_lib_glsl, + datatoc_ssr_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_cubemap_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_ltc_lib_glsl, + datatoc_lights_lib_glsl, + /* Add one for each Closure */ + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_volumetric_lib_glsl); + + e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_cubemap_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_ltc_lib_glsl, + datatoc_lights_lib_glsl, + datatoc_volumetric_lib_glsl, + datatoc_volumetric_frag_glsl); + + e_data.vert_shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl); + + e_data.vert_shadow_shader_str = BLI_string_joinN( + datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl); + + e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_background_vert_glsl); + + e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_volumetric_vert_glsl); + + e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_volumetric_geom_glsl); +} + GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void) { return e_data.probe_filter_glossy_sh; @@ -292,6 +405,26 @@ GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void) return e_data.velocity_resolve_sh; } +GPUShader *EEVEE_shaders_default_background_sh_get(void) +{ + if (e_data.default_background == NULL) { + e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl, + NULL, + datatoc_default_world_frag_glsl, + datatoc_common_view_lib_glsl, + NULL); + } + return e_data.default_background; +} + +GPUShader *EEVEE_shaders_update_noise_sh_get(void) +{ + if (e_data.update_noise_sh == NULL) { + e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL); + } + return e_data.update_noise_sh; +} + GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects) { GPUShader **sh; @@ -316,8 +449,330 @@ GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects) return *sh; } +Material *EEVEE_material_default_diffuse_get(void) +{ + if (!e_data.diffuse_mat) { + Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default diffuse"); + + bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + ma->nodetree = ntree; + ma->use_nodes = true; + + bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_DIFFUSE); + bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color"); + copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.8f); + + bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); + + nodeAddLink(ntree, + bsdf, + nodeFindSocket(bsdf, SOCK_OUT, "BSDF"), + output, + nodeFindSocket(output, SOCK_IN, "Surface")); + + nodeSetActive(ntree, output); + e_data.diffuse_mat = ma; + } + return e_data.diffuse_mat; +} + +Material *EEVEE_material_default_glossy_get(void) +{ + if (!e_data.glossy_mat) { + Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal"); + + bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + ma->nodetree = ntree; + ma->use_nodes = true; + + bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_GLOSSY); + bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color"); + copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f); + bNodeSocket *roughness = nodeFindSocket(bsdf, SOCK_IN, "Roughness"); + ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f; + + bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); + + nodeAddLink(ntree, + bsdf, + nodeFindSocket(bsdf, SOCK_OUT, "BSDF"), + output, + nodeFindSocket(output, SOCK_IN, "Surface")); + + nodeSetActive(ntree, output); + e_data.glossy_mat = ma; + } + return e_data.glossy_mat; +} + +Material *EEVEE_material_default_error_get(void) +{ + if (!e_data.error_mat) { + Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal"); + + bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + ma->nodetree = ntree; + ma->use_nodes = true; + + /* Use emission and output material to be compatible with both World and Material. */ + bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION); + bNodeSocket *color = nodeFindSocket(bsdf, SOCK_IN, "Color"); + copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f); + + bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); + + nodeAddLink(ntree, + bsdf, + nodeFindSocket(bsdf, SOCK_OUT, "Emission"), + output, + nodeFindSocket(output, SOCK_IN, "Surface")); + + nodeSetActive(ntree, output); + e_data.error_mat = ma; + } + return e_data.error_mat; +} + +/* Configure a default nodetree with the given material. */ +struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma) +{ + /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */ + if (!e_data.surface.ntree) { + bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_PRINCIPLED); + bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL); + bNodeSocket *bsdf_out = nodeFindSocket(bsdf, SOCK_OUT, "BSDF"); + bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface"); + nodeAddLink(ntree, bsdf, bsdf_out, output, output_in); + nodeSetActive(ntree, output); + + e_data.surface.color_socket = nodeFindSocket(bsdf, SOCK_IN, "Base Color")->default_value; + e_data.surface.metallic_socket = nodeFindSocket(bsdf, SOCK_IN, "Metallic")->default_value; + e_data.surface.roughness_socket = nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value; + e_data.surface.specular_socket = nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value; + e_data.surface.ntree = ntree; + } + /* Update */ + copy_v3_fl3(e_data.surface.color_socket->value, ma->r, ma->g, ma->b); + e_data.surface.metallic_socket->value = ma->metallic; + e_data.surface.roughness_socket->value = ma->roughness; + e_data.surface.specular_socket->value = ma->spec; + + return e_data.surface.ntree; +} + +/* Configure a default nodetree with the given world. */ +struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo) +{ + /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */ + if (!e_data.world.ntree) { + bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname); + bNode *bg = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND); + bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD); + bNodeSocket *bg_out = nodeFindSocket(bg, SOCK_OUT, "Background"); + bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface"); + nodeAddLink(ntree, bg, bg_out, output, output_in); + nodeSetActive(ntree, output); + + e_data.world.color_socket = nodeFindSocket(bg, SOCK_IN, "Color")->default_value; + e_data.world.ntree = ntree; + } + + copy_v3_fl3(e_data.world.color_socket->value, wo->horr, wo->horg, wo->horb); + + return e_data.world.ntree; +} + +static char *eevee_get_defines(int options) +{ + char *str = NULL; + + DynStr *ds = BLI_dynstr_new(); + BLI_dynstr_append(ds, SHADER_DEFINES); + + if ((options & VAR_WORLD_BACKGROUND) != 0) { + BLI_dynstr_append(ds, "#define WORLD_BACKGROUND\n"); + } + if ((options & VAR_MAT_VOLUME) != 0) { + BLI_dynstr_append(ds, "#define VOLUMETRICS\n"); + } + if ((options & VAR_MAT_MESH) != 0) { + BLI_dynstr_append(ds, "#define MESH_SHADER\n"); + } + if ((options & VAR_MAT_DEPTH) != 0) { + BLI_dynstr_append(ds, "#define DEPTH_SHADER\n"); + } + if ((options & VAR_MAT_HAIR) != 0) { + BLI_dynstr_append(ds, "#define HAIR_SHADER\n"); + } + if ((options & (VAR_MAT_PROBE | VAR_WORLD_PROBE)) != 0) { + BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n"); + } + if ((options & VAR_MAT_HASH) != 0) { + BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n"); + } + if ((options & VAR_MAT_BLEND) != 0) { + BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n"); + } + if ((options & VAR_MAT_REFRACT) != 0) { + BLI_dynstr_append(ds, "#define USE_REFRACTION\n"); + } + if ((options & VAR_MAT_LOOKDEV) != 0) { + BLI_dynstr_append(ds, "#define LOOKDEV\n"); + } + if ((options & VAR_MAT_HOLDOUT) != 0) { + BLI_dynstr_append(ds, "#define HOLDOUT\n"); + } + + str = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return str; +} + +static char *eevee_get_vert(int options) +{ + char *str = NULL; + + if ((options & VAR_MAT_VOLUME) != 0) { + str = BLI_strdup(e_data.vert_volume_shader_str); + } + else if ((options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0) { + str = BLI_strdup(e_data.vert_background_shader_str); + } + else { + str = BLI_strdup(e_data.vert_shader_str); + } + + return str; +} + +static char *eevee_get_geom(int options) +{ + char *str = NULL; + + if ((options & VAR_MAT_VOLUME) != 0) { + str = BLI_strdup(e_data.geom_volume_shader_str); + } + + return str; +} + +static char *eevee_get_frag(int options) +{ + char *str = NULL; + + if ((options & VAR_MAT_VOLUME) != 0) { + str = BLI_strdup(e_data.volume_shader_lib); + } + else if ((options & VAR_MAT_DEPTH) != 0) { + str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl); + } + else { + str = BLI_strdup(e_data.frag_shader_lib); + } + + return str; +} + +static struct GPUMaterial *eevee_material_get_ex( + struct Scene *scene, Material *ma, World *wo, int options, bool deferred) +{ + BLI_assert(ma || wo); + const bool is_volume = (options & VAR_MAT_VOLUME) != 0; + const bool is_default = (options & VAR_DEFAULT) != 0; + const void *engine = &DRW_engine_viewport_eevee_type; + + GPUMaterial *mat = NULL; + + if (ma) { + mat = DRW_shader_find_from_material(ma, engine, options, deferred); + } + else { + mat = DRW_shader_find_from_world(wo, engine, options, deferred); + } + + if (mat) { + return mat; + } + + char *defines = eevee_get_defines(options); + char *vert = eevee_get_vert(options); + char *geom = eevee_get_geom(options); + char *frag = eevee_get_frag(options); + + if (ma) { + bNodeTree *ntree = !is_default ? ma->nodetree : EEVEE_shader_default_surface_nodetree(ma); + mat = DRW_shader_create_from_material( + scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred); + } + else { + bNodeTree *ntree = !is_default ? wo->nodetree : EEVEE_shader_default_world_nodetree(wo); + mat = DRW_shader_create_from_world( + scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred); + } + + MEM_SAFE_FREE(defines); + MEM_SAFE_FREE(vert); + MEM_SAFE_FREE(geom); + MEM_SAFE_FREE(frag); + + return mat; +} + +/* Note: Compilation is not deferred. */ +struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options) +{ + Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() : + BKE_material_default_surface(); + BLI_assert(def_ma->use_nodes && def_ma->nodetree); + + return eevee_material_get_ex(scene, def_ma, NULL, options, false); +} + +struct GPUMaterial *EEVEE_material_get( + EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options) +{ + if ((ma && (!ma->use_nodes || !ma->nodetree)) || (wo && (!wo->use_nodes || !wo->nodetree))) { + options |= VAR_DEFAULT; + } + + /* Meh, implicit option. World probe cannot be deferred because they need + * to be rendered immediatly. */ + const bool deferred = (options & VAR_WORLD_PROBE) == 0; + + GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred); + + int status = GPU_material_status(mat); + switch (status) { + case GPU_MAT_SUCCESS: + break; + case GPU_MAT_QUEUED: + vedata->stl->g_data->queued_shaders_count++; + mat = EEVEE_material_default_get(scene, ma, options); + break; + case GPU_MAT_FAILED: + default: + ma = EEVEE_material_default_error_get(); + mat = eevee_material_get_ex(scene, ma, NULL, options, false); + break; + } + /* Returned material should be ready to be drawn. */ + BLI_assert(GPU_material_status(mat) == GPU_MAT_SUCCESS); + return mat; +} + void EEVEE_shaders_free(void) { + MEM_SAFE_FREE(e_data.frag_shader_lib); + MEM_SAFE_FREE(e_data.vert_shader_str); + MEM_SAFE_FREE(e_data.vert_shadow_shader_str); + MEM_SAFE_FREE(e_data.vert_background_shader_str); + MEM_SAFE_FREE(e_data.vert_volume_shader_str); + MEM_SAFE_FREE(e_data.geom_volume_shader_str); + MEM_SAFE_FREE(e_data.volume_shader_lib); + DRW_SHADER_FREE_SAFE(e_data.default_background); + DRW_SHADER_FREE_SAFE(e_data.update_noise_sh); DRW_SHADER_FREE_SAFE(e_data.probe_default_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh); DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh); @@ -332,4 +787,27 @@ void EEVEE_shaders_free(void) DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh); DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh); + + if (e_data.glossy_mat) { + BKE_id_free(NULL, e_data.glossy_mat); + e_data.glossy_mat = NULL; + } + if (e_data.diffuse_mat) { + BKE_id_free(NULL, e_data.diffuse_mat); + e_data.diffuse_mat = NULL; + } + if (e_data.error_mat) { + BKE_id_free(NULL, e_data.error_mat); + e_data.error_mat = NULL; + } + if (e_data.surface.ntree) { + ntreeFreeEmbeddedTree(e_data.surface.ntree); + MEM_freeN(e_data.surface.ntree); + e_data.surface.ntree = NULL; + } + if (e_data.world.ntree) { + ntreeFreeEmbeddedTree(e_data.world.ntree); + MEM_freeN(e_data.world.ntree); + e_data.world.ntree = NULL; + } } diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index fb338d85fde..84c50a22ae6 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -159,47 +159,6 @@ void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } } -/* Add a shadow caster to the shadowpasses */ -void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *UNUSED(sldata), - EEVEE_StorageList *stl, - struct GPUBatch *geom, - Object *ob) -{ - DRW_shgroup_call(stl->g_data->shadow_shgrp, geom, ob); -} - -void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata, - EEVEE_PassList *psl, - struct GPUMaterial *gpumat, - struct GPUBatch *geom, - struct Object *ob, - const float *alpha_threshold) -{ - /* TODO / PERF : reuse the same shading group for objects with the same material */ - DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass); - - if (grp == NULL) { - return; - } - - /* Unfortunately needed for correctness but not 99% of the time not needed. - * TODO detect when needed? */ - DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); - DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - - if (alpha_threshold != NULL) { - DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1); - } - - DRW_shgroup_call(grp, geom, ob); -} - /* Make that object update shadow casting lights inside its influence bounding box. */ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob) { @@ -470,8 +429,7 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool); DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool); diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 4f334812a8e..7674148f76a 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -29,7 +29,9 @@ #include "DEG_depsgraph_query.h" #include "GPU_extensions.h" +#include "GPU_material.h" #include "GPU_texture.h" + #include "eevee_private.h" static struct { @@ -83,6 +85,7 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2; + effects->sss_surface_count = 0; common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold; } @@ -221,70 +224,77 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - uint sss_id, - struct GPUUniformBuffer *sss_profile) + Material *ma, + DRWShadingGroup *shgrp, + struct GPUMaterial *gpumat) { - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; - struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps); - DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); - DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance); - DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); - DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); - DRW_shgroup_stencil_mask(grp, sss_id); - DRW_shgroup_call(grp, quad, NULL); - - grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps); - DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); - DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur); - DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); - DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); - DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); - DRW_shgroup_stencil_mask(grp, sss_id); - DRW_shgroup_call(grp, quad, NULL); -} + struct GPUTexture *sss_tex_profile = NULL; + struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get( + gpumat, stl->effects->sss_sample_count, &sss_tex_profile); -void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata, - EEVEE_Data *vedata, - uint sss_id, - struct GPUUniformBuffer *sss_profile, - GPUTexture *sss_tex_profile) -{ - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_EffectsInfo *effects = stl->effects; - struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); - GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth; + if (!sss_profile) { + BLI_assert(0 && "SSS pass requested but no SSS data was found"); + return; + } + + /* Limit of 8 bit stencil buffer. ID 255 is refraction. */ + if (effects->sss_surface_count >= 254) { + /* TODO : display message. */ + printf("Error: Too many different Subsurface shader in the scene.\n"); + return; + } + + int sss_id = ++(effects->sss_surface_count); + /* Make main pass output stencil mask. */ + DRW_shgroup_stencil_mask(shgrp, sss_id); + + { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); + DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance); + DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); + DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); + DRW_shgroup_stencil_mask(grp, sss_id); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + + grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); + DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur); + DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo); + DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); + DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); + DRW_shgroup_stencil_mask(grp, sss_id); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } - DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps); - DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); - DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); - DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); - DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool); - DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool); - DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); - DRW_shgroup_stencil_mask(grp, sss_id); - DRW_shgroup_call(grp, quad, NULL); + if (ma->blend_flag & MA_BL_TRANSLUCENCY) { + DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); + DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius); + DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool); + DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool); + DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); + DRW_shgroup_stencil_mask(grp, sss_id); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } } void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) @@ -310,8 +320,7 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)}); GPU_framebuffer_bind(fbl->main_fb); - DRW_draw_pass(psl->sss_pass); - DRW_draw_pass(psl->sss_pass_cull); + DRW_draw_pass(psl->material_sss_ps); /* Restore */ GPU_framebuffer_ensure_config(&fbl->main_fb, @@ -350,23 +359,15 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) if (!DRW_pass_is_empty(psl->sss_translucency_ps)) { /* We sample the shadow-maps using normal sampler. We need to disable Comparison mode. * TODO(fclem) avoid this by using sampler objects.*/ - GPU_texture_bind(sldata->shadow_cube_pool, 0); GPU_texture_compare_mode(sldata->shadow_cube_pool, false); - GPU_texture_unbind(sldata->shadow_cube_pool); - GPU_texture_bind(sldata->shadow_cascade_pool, 0); GPU_texture_compare_mode(sldata->shadow_cascade_pool, false); - GPU_texture_unbind(sldata->shadow_cascade_pool); GPU_framebuffer_bind(fbl->sss_translucency_fb); DRW_draw_pass(psl->sss_translucency_ps); /* Reset original state. */ - GPU_texture_bind(sldata->shadow_cube_pool, 0); GPU_texture_compare_mode(sldata->shadow_cube_pool, true); - GPU_texture_unbind(sldata->shadow_cube_pool); - GPU_texture_bind(sldata->shadow_cascade_pool, 0); GPU_texture_compare_mode(sldata->shadow_cascade_pool, true); - GPU_texture_unbind(sldata->shadow_cascade_pool); } /* 1. horizontal pass */ diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index b70d872c4af..d57048f2c4e 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -292,8 +292,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history); DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); if (effects->enabled_effects & EFFECT_TAA_REPROJECT) { // DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 83bd4fcf8d2..90860e94270 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -355,7 +355,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) struct World *wo = scene->world; if (wo != NULL && wo->use_nodes && wo->nodetree && !LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) { - struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo); + struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_MAT_VOLUME); if (GPU_material_has_volume_output(mat)) { grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps); @@ -369,8 +369,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); /* Fix principle volumetric not working with world materials. */ ListBase gpu_grids = GPU_material_volume_grids(mat); @@ -388,8 +387,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* If no world or volume material is present just clear the buffer with this drawcall */ grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); } @@ -590,12 +588,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, return; } - struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma); + int mat_options = VAR_MAT_VOLUME | VAR_MAT_MESH; + struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options); eGPUMaterialStatus status = GPU_material_status(mat); - if (status == GPU_MAT_QUEUED) { - vedata->stl->g_data->queued_shaders_count++; - } /* If shader failed to compile or is currently compiling. */ if (status != GPU_MAT_SUCCESS) { return; @@ -609,8 +605,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); @@ -661,8 +656,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); @@ -671,8 +665,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter); DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call_procedural_triangles( grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]); @@ -683,8 +676,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit); DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); DRW_shgroup_call_procedural_triangles(grp, NULL, 1); } @@ -775,12 +767,8 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* We sample the shadow-maps using shadow sampler. We need to enable Comparison mode. * TODO(fclem) avoid this by using sampler objects.*/ - GPU_texture_bind(sldata->shadow_cube_pool, 0); GPU_texture_compare_mode(sldata->shadow_cube_pool, true); - GPU_texture_unbind(sldata->shadow_cube_pool); - GPU_texture_bind(sldata->shadow_cascade_pool, 0); GPU_texture_compare_mode(sldata->shadow_cascade_pool, true); - GPU_texture_unbind(sldata->shadow_cascade_pool); GPU_framebuffer_bind(fbl->volumetric_fb); DRW_draw_pass(psl->volumetric_world_ps); @@ -920,8 +908,7 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit); DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src); DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); - DRW_shgroup_uniform_block( - grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined); } else { /* There is no volumetrics in the scene. Use a shader to fill the accum textures with a default diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl index 8662c0ecb6a..57b16418696 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -6,13 +6,9 @@ #if defined(MESH_SHADER) # if !defined(USE_ALPHA_HASH) -# if !defined(USE_ALPHA_CLIP) -# if !defined(SHADOW_SHADER) -# if !defined(USE_MULTIPLY) -# if !defined(USE_ALPHA_BLEND) -# define ENABLE_DEFERED_AO -# endif -# endif +# if !defined(DEPTH_SHADER) +# if !defined(USE_ALPHA_BLEND) +# define ENABLE_DEFERED_AO # endif # endif # endif diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index c3518198805..402d306df45 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -928,7 +928,7 @@ Closure closure_emission(vec3 rgb) /* Breaking this across multiple lines causes issues for some older GLSL compilers. */ /* clang-format off */ -# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) +# if defined(MESH_SHADER) && !defined(DEPTH_SHADER) /* clang-format on */ # ifndef USE_ALPHA_BLEND layout(location = 0) out vec4 outRadiance; @@ -1001,6 +1001,10 @@ void main() outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac; # endif +# ifdef LOOKDEV + gl_FragDepth = 0.0; +# endif + # ifndef USE_ALPHA_BLEND float alpha_div = 1.0 / max(1e-8, alpha); outRadiance.rgb *= alpha_div; @@ -1011,6 +1015,6 @@ void main() # endif } -# endif /* MESH_SHADER && !SHADOW_SHADER */ +# endif /* MESH_SHADER */ #endif /* VOLUMETRICS */ diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl index 5277bfa32bb..d56890769a7 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl @@ -1,6 +1,4 @@ -uniform mat4 ProjectionMatrix; - uniform sampler2D colorBuffer; uniform sampler2D depthBuffer; diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index 8c2619650b9..bc7879763c3 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -177,7 +177,7 @@ void CLOSURE_NAME(vec3 N out_refr = vec3(0.0); #endif -#if defined(SHADOW_SHADER) || defined(WORLD_BACKGROUND) +#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND) /* This makes shader resources become unused and avoid issues with samplers. (see T59747) */ return; #else diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl index cf20b3ff5b9..1b94fc2bee1 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl @@ -4,11 +4,12 @@ in vec3 pos; in vec3 nor; #endif +#ifdef MESH_SHADER out vec3 worldPosition; out vec3 viewPosition; - out vec3 worldNormal; out vec3 viewNormal; +#endif #ifdef HAIR_SHADER out vec3 hairTangent; @@ -41,22 +42,28 @@ void main() hairThickness, hairThickTime); worldNormal = cross(hairTangent, binor); - worldPosition = pos; + vec3 world_pos = pos; #else - worldPosition = point_object_to_world(pos); - worldNormal = normalize(normal_object_to_world(nor)); + vec3 world_pos = point_object_to_world(pos); #endif - /* No need to normalize since this is just a rotation. */ - viewNormal = normal_world_to_view(worldNormal); + gl_Position = point_world_to_ndc(world_pos); + /* Used for planar reflections */ + gl_ClipDistance[0] = dot(vec4(world_pos, 1.0), clipPlanes[0]); + +#ifdef MESH_SHADER + worldPosition = world_pos; viewPosition = point_world_to_view(worldPosition); - gl_Position = point_world_to_ndc(worldPosition); - /* Used for planar reflections */ - gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), clipPlanes[0]); +# ifndef HAIR_SHADER + worldNormal = normalize(normal_object_to_world(nor)); +# endif -#ifdef USE_ATTR + /* No need to normalize since this is just a rotation. */ + viewNormal = normal_world_to_view(worldNormal); +# ifdef USE_ATTR pass_attr(pos); +# endif #endif } diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl index b49dbfceba2..9acd8f998f6 100644 --- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl @@ -45,26 +45,22 @@ float hashed_alpha_threshold(vec3 co) /* Find our final, uniformly distributed alpha threshold. */ float threshold = (x < one_a) ? ((x < a) ? cases.x : cases.y) : cases.z; + /* Jitter the threshold for TAA accumulation. */ + threshold = fract(threshold + alphaHashOffset); + /* Avoids threshold == 0. */ threshold = clamp(threshold, 1.0e-6, 1.0); - /* Jitter the threshold for TAA accumulation. */ - return fract(threshold + alphaHashOffset); + return threshold; } #endif -#ifdef USE_ALPHA_CLIP -uniform float alphaThreshold; -#endif +#define NODETREE_EXEC void main() { - /* For now do nothing. - * In the future, output object motion blur. */ - -#if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP) -# define NODETREE_EXEC +#if defined(USE_ALPHA_HASH) Closure cl = nodetree_exec(); @@ -75,11 +71,6 @@ void main() if (opacity < hashed_alpha_threshold(worldPosition)) { discard; } -# elif defined(USE_ALPHA_CLIP) - /* Alpha clip */ - if (opacity <= alphaThreshold) { - discard; - } # endif #endif } diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 6e636e4dc93..2f448b784ed 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -44,6 +44,11 @@ #define EXTERNAL_ENGINE "BLENDER_EXTERNAL" +extern char datatoc_depth_frag_glsl[]; +extern char datatoc_depth_vert_glsl[]; + +extern char datatoc_common_view_lib_glsl[]; + /* *********** LISTS *********** */ /* GPUViewport.storage @@ -106,7 +111,16 @@ static void external_engine_init(void *vedata) /* Depth prepass */ if (!e_data.depth_sh) { - e_data.depth_sh = DRW_shader_create_3d_depth_only(GPU_SHADER_CFG_DEFAULT); + const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[GPU_SHADER_CFG_DEFAULT]; + + e_data.depth_sh = GPU_shader_create_from_arrays({ + .vert = (const char *[]){sh_cfg->lib, + datatoc_common_view_lib_glsl, + datatoc_depth_vert_glsl, + NULL}, + .frag = (const char *[]){datatoc_depth_frag_glsl, NULL}, + .defs = (const char *[]){sh_cfg->def, NULL}, + }); } if (!stl->g_data) { @@ -277,7 +291,7 @@ static void external_draw_scene(void *vedata) static void external_engine_free(void) { - /* All shaders are builtin. */ + DRW_SHADER_FREE_SAFE(e_data.depth_sh); } static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data); diff --git a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c index 4dd5e3b2da1..8955240c549 100644 --- a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c +++ b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c @@ -78,13 +78,8 @@ void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata) false, NULL); - GPU_texture_bind(txl->smaa_search_tx, 0); GPU_texture_filter_mode(txl->smaa_search_tx, true); - GPU_texture_unbind(txl->smaa_search_tx); - - GPU_texture_bind(txl->smaa_area_tx, 0); GPU_texture_filter_mode(txl->smaa_area_tx, true); - GPU_texture_unbind(txl->smaa_area_tx); } { diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index 1344b649dff..2b811f1d52e 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -381,7 +381,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, struct GPUShader *sh = GPENCIL_shader_geometry_get(); DRWShadingGroup *grp = tgp_layer->base_shgrp = DRW_shgroup_create(sh, tgp_layer->geom_ps); - DRW_shgroup_uniform_texture_persistent(grp, "gpSceneDepthTexture", depth_tex); + DRW_shgroup_uniform_texture(grp, "gpSceneDepthTexture", depth_tex); DRW_shgroup_uniform_texture_ref(grp, "gpMaskTexture", mask_tex); DRW_shgroup_uniform_vec3_copy(grp, "gpNormal", tgp_ob->plane_normal); DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", tgp_ob->is_drawmode3d); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 4f586a1e9f3..495de7ef10b 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -91,6 +91,7 @@ void GPENCIL_engine_init(void *ved) stl->pd->gp_object_pool = vldata->gp_object_pool; stl->pd->gp_layer_pool = vldata->gp_layer_pool; stl->pd->gp_vfx_pool = vldata->gp_vfx_pool; + stl->pd->view_layer = ctx->view_layer; stl->pd->scene = ctx->scene; stl->pd->v3d = ctx->v3d; stl->pd->last_light_pool = NULL; @@ -468,7 +469,7 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl, /* Iterator dependent uniforms. */ DRWShadingGroup *grp = iter->grp = tgp_layer->base_shgrp; - DRW_shgroup_uniform_block_persistent(grp, "gpLightBlock", iter->ubo_lights); + DRW_shgroup_uniform_block(grp, "gpLightBlock", iter->ubo_lights); DRW_shgroup_uniform_block(grp, "gpMaterialBlock", iter->ubo_mat); DRW_shgroup_uniform_texture(grp, "gpFillTexture", iter->tex_fill); DRW_shgroup_uniform_texture(grp, "gpStrokeTexture", iter->tex_stroke); @@ -598,6 +599,7 @@ void GPENCIL_cache_populate(void *ved, Object *ob) GPENCIL_Data *vedata = (GPENCIL_Data *)ved; GPENCIL_PrivateData *pd = vedata->stl->pd; GPENCIL_TextureList *txl = vedata->txl; + const bool is_final_render = DRW_state_is_image_render(); /* object must be visible */ if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) { @@ -617,7 +619,8 @@ void GPENCIL_cache_populate(void *ved, Object *ob) bGPdata *gpd = (bGPdata *)ob->data; bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS); - BKE_gpencil_visible_stroke_iter(ob, + BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL, + ob, gpencil_layer_cache_populate, gpencil_stroke_cache_populate, &iter, diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index f765dcf73de..cedd75af813 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -307,6 +307,8 @@ typedef struct GPENCIL_PrivateData { float dof_params[2]; /* Used for DoF Setup. */ Object *camera; + /* Copy of draw_ctx->view_layer for convenience. */ + struct ViewLayer *view_layer; /* Copy of draw_ctx->scene for convenience. */ struct Scene *scene; /* Copy of draw_ctx->vie3d for convenience. */ diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index a538b7ffd5f..95fd918f8c1 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -184,7 +184,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_sphere(false); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f); cb->point_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get()); @@ -196,7 +196,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_shape(false); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f); cb->custom_solid = grp; cb->box_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get()); @@ -212,29 +212,29 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_sphere(true); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->point_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get()); sh = OVERLAY_shader_armature_shape(true); cb->custom_outline = grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->box_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_box_wire_get()); cb->octa_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_octahedral_wire_get()); sh = OVERLAY_shader_armature_shape_wire(); cb->custom_wire = grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } { format = formats->instance_extra; sh = OVERLAY_shader_armature_degrees_of_freedom(); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->dof_lines = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_lines_get()); grp = DRW_shgroup_create(sh, armature_transp_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->dof_sphere = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_sphere_get()); } { @@ -242,7 +242,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_stick(); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->stick = BUF_INSTANCE(grp, format, DRW_cache_bone_stick_get()); } { @@ -251,7 +251,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_envelope(false); grp = DRW_shgroup_create(sh, armature_ps); DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "isDistance", false); DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f); cb->envelope_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get()); @@ -266,14 +266,14 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_envelope(true); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->envelope_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_outline_get()); format = formats->instance_bone_envelope_distance; sh = OVERLAY_shader_armature_envelope(false); grp = DRW_shgroup_create(sh, armature_transp_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "isDistance", true); DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); cb->envelope_distance = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get()); @@ -283,7 +283,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_armature_wire(); grp = DRW_shgroup_create(sh, armature_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->wire = BUF_LINE(grp, format); } } diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index 71efc6b8d03..859f3f93b1d 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -81,8 +81,8 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) struct GPUTexture *tex = DRW_state_is_fbo() ? dtxl->depth : txl->dummy_depth_tx; pd->extra_grid_grp = grp = DRW_shgroup_create(sh, psl->extra_grid_ps); - DRW_shgroup_uniform_texture_persistent(grp, "depthBuffer", tex); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_texture(grp, "depthBuffer", tex); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0); } @@ -112,7 +112,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_extra(is_select); grp = DRW_shgroup_create(sh, extra_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); grp_sub = DRW_shgroup_create_sub(grp); cb->camera_distances = BUF_INSTANCE(grp_sub, format, DRW_cache_camera_distances_get()); @@ -157,7 +157,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) { format = formats->instance_extra; grp = DRW_shgroup_create(sh, psl->extra_blend_ps); /* NOTE: not the same pass! */ - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); grp_sub = DRW_shgroup_create_sub(grp); DRW_shgroup_state_enable(grp_sub, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK); @@ -174,7 +174,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_extra_groundline(); grp = DRW_shgroup_create(sh, extra_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA); cb->groundline = BUF_INSTANCE(grp, format, DRW_cache_groundline_get()); @@ -183,7 +183,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_extra_wire(false, is_select); grp = DRW_shgroup_create(sh, extra_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); cb->extra_dashed_lines = BUF_LINE(grp, formats->pos_color); cb->extra_lines = BUF_LINE(grp, formats->wire_extra); @@ -192,20 +192,20 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_extra_wire(true, is_select); cb->extra_wire = grp = DRW_shgroup_create(sh, extra_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } { sh = OVERLAY_shader_extra_loose_point(); cb->extra_loose_points = grp = DRW_shgroup_create(sh, extra_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } { format = formats->pos; sh = OVERLAY_shader_extra_point(); grp = DRW_shgroup_create(sh, psl->extra_centers_ps); /* NOTE: not the same pass! */ - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); grp_sub = DRW_shgroup_create_sub(grp); DRW_shgroup_uniform_vec4_copy(grp_sub, "color", G_draw.block.colorActive); @@ -1371,9 +1371,9 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb, madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, mds->cell_size, mds->res_min); float voxel_cubemat[4][4] = {{0.0f}}; /* scale small cube to voxel size */ - voxel_cubemat[0][0] = 1.0f / (float)mds->base_res[0]; - voxel_cubemat[1][1] = 1.0f / (float)mds->base_res[1]; - voxel_cubemat[2][2] = 1.0f / (float)mds->base_res[2]; + voxel_cubemat[0][0] = mds->cell_size[0] / 2.0f; + voxel_cubemat[1][1] = mds->cell_size[1] / 2.0f; + voxel_cubemat[2][2] = mds->cell_size[2] / 2.0f; voxel_cubemat[3][3] = 1.0f; /* translate small cube to corner */ copy_v3_v3(voxel_cubemat[3], min); diff --git a/source/blender/draw/engines/overlay/overlay_facing.c b/source/blender/draw/engines/overlay/overlay_facing.c index 9216ae61b3e..4eb4b8ae85b 100644 --- a/source/blender/draw/engines/overlay/overlay_facing.c +++ b/source/blender/draw/engines/overlay/overlay_facing.c @@ -41,7 +41,7 @@ void OVERLAY_facing_cache_init(OVERLAY_Data *vedata) GPUShader *sh = OVERLAY_shader_facing(); pd->facing_grp[i] = DRW_shgroup_create(sh, psl->facing_ps[i]); - DRW_shgroup_uniform_block_persistent(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo); } if (!pd->use_in_front) { diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c index 1397ef7b4b2..ccc914e0422 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.c +++ b/source/blender/draw/engines/overlay/overlay_gpencil.c @@ -361,7 +361,7 @@ static void OVERLAY_gpencil_color_names(Object *ob) int cfra = DEG_get_ctime(draw_ctx->depsgraph); BKE_gpencil_visible_stroke_iter( - ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra); + NULL, ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra); } void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob) diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.c b/source/blender/draw/engines/overlay/overlay_motion_path.c index 531e1faf715..168f6f8a17f 100644 --- a/source/blender/draw/engines/overlay/overlay_motion_path.c +++ b/source/blender/draw/engines/overlay/overlay_motion_path.c @@ -49,11 +49,11 @@ void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_motion_path_line(); pd->motion_path_lines_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); sh = OVERLAY_shader_motion_path_vert(); pd->motion_path_points_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } /* Just convert the CPU cache to GPU cache. */ diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c index 142421f58d8..99d22fc380f 100644 --- a/source/blender/draw/engines/overlay/overlay_outline.c +++ b/source/blender/draw/engines/overlay/overlay_outline.c @@ -259,7 +259,7 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob) } BKE_gpencil_visible_stroke_iter( - ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra); + NULL, ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra); } void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata, diff --git a/source/blender/draw/engines/overlay/overlay_particle.c b/source/blender/draw/engines/overlay/overlay_particle.c index 98bc62ae66a..b891bb4ce4c 100644 --- a/source/blender/draw/engines/overlay/overlay_particle.c +++ b/source/blender/draw/engines/overlay/overlay_particle.c @@ -152,13 +152,13 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_particle_dot(); pd->particle_dots_grp = grp = DRW_shgroup_create(sh, psl->particle_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp); sh = OVERLAY_shader_particle_shape(); pd->particle_shapes_grp = grp = DRW_shgroup_create(sh, psl->particle_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); - DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp); } void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob) diff --git a/source/blender/draw/engines/overlay/overlay_pointcloud.c b/source/blender/draw/engines/overlay/overlay_pointcloud.c index a0de7aac1f1..b2a2d44bf73 100644 --- a/source/blender/draw/engines/overlay/overlay_pointcloud.c +++ b/source/blender/draw/engines/overlay/overlay_pointcloud.c @@ -46,7 +46,7 @@ void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata) sh = OVERLAY_shader_pointcloud_dot(); pd->pointcloud_dots_grp = grp = DRW_shgroup_create(sh, psl->pointcloud_ps); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); } void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob) diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index cb36f0ed326..eebfc88fdce 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -91,7 +91,7 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata) for (int use_coloring = 0; use_coloring < 2; use_coloring++) { pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass); - DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo); + DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo); DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx); DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param); DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring); @@ -197,13 +197,15 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, struct GPUBatch *geom = NULL; switch (ob->type) { case OB_CURVE: - if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) { + if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache && + BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) { break; } geom = DRW_cache_curve_edge_wire_get(ob); break; case OB_FONT: - if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) { + if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache && + BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) { break; } geom = DRW_cache_text_loose_edges_get(ob); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl index 0efcfb35929..51007a9f246 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl @@ -4,7 +4,6 @@ * Converted and adapted from HLSL to GLSL by Clément Foucault */ -uniform mat4 ProjectionMatrix; uniform vec2 invertedViewportSize; uniform vec2 nearFar; uniform vec3 dofParams; diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c index cb8eb7d1e92..0e896c4b7bb 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c +++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c @@ -266,13 +266,8 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata) false, NULL); - GPU_texture_bind(txl->smaa_search_tx, 0); GPU_texture_filter_mode(txl->smaa_search_tx, true); - GPU_texture_unbind(txl->smaa_search_tx); - - GPU_texture_bind(txl->smaa_area_tx, 0); GPU_texture_filter_mode(txl->smaa_area_tx, true); - GPU_texture_unbind(txl->smaa_area_tx); } } else { diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 0b7d313342b..b36a4a3a494 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -284,11 +284,11 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd, *grp_tex = grp = DRW_shgroup_create_sub(grp); if (tex_tile_data) { - DRW_shgroup_uniform_texture_persistent(grp, "imageTileArray", tex); - DRW_shgroup_uniform_texture_persistent(grp, "imageTileData", tex_tile_data); + DRW_shgroup_uniform_texture(grp, "imageTileArray", tex); + DRW_shgroup_uniform_texture(grp, "imageTileData", tex_tile_data); } else { - DRW_shgroup_uniform_texture_persistent(grp, "imageTexture", tex); + DRW_shgroup_uniform_texture(grp, "imageTexture", tex); } DRW_shgroup_uniform_bool_copy(grp, "imagePremult", (ima && ima->alpha_mode == IMA_ALPHA_PREMUL)); DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST)); diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c index c9c43e785ca..27d5b71f35c 100644 --- a/source/blender/draw/engines/workbench/workbench_opaque.c +++ b/source/blender/draw/engines/workbench/workbench_opaque.c @@ -95,21 +95,21 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data) DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); wpd->prepass[opaque][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr); + DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); sh = workbench_shader_opaque_image_get(wpd, hair, false); wpd->prepass[opaque][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr); + DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); sh = workbench_shader_opaque_image_get(wpd, hair, true); wpd->prepass[opaque][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr); + DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap); } @@ -123,9 +123,9 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data) sh = workbench_shader_composite_get(wpd); grp = DRW_shgroup_create(sh, psl->composite_ps); - DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo); - DRW_shgroup_uniform_texture_persistent(grp, "materialBuffer", wpd->material_buffer_tx); - DRW_shgroup_uniform_texture_persistent(grp, "normalBuffer", wpd->normal_buffer_tx); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_texture(grp, "materialBuffer", wpd->material_buffer_tx); + DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx); DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false); DRW_shgroup_stencil_mask(grp, 0x00); @@ -137,8 +137,8 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data) struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture; const bool use_spec = workbench_is_specular_highlight_enabled(wpd); spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx; - DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx); - DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx); + DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx); + DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx); } DRW_shgroup_call_procedural_triangles(grp, NULL, 1); diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c index 2e796056029..99366779b22 100644 --- a/source/blender/draw/engines/workbench/workbench_shader.c +++ b/source/blender/draw/engines/workbench/workbench_shader.c @@ -23,6 +23,7 @@ #include "DRW_render.h" #include "BLI_dynstr.h" +#include "BLI_string_utils.h" #include "workbench_engine.h" #include "workbench_private.h" @@ -359,32 +360,24 @@ void workbench_shader_depth_of_field_get(GPUShader **prepare_sh, GPUShader **resolve_sh) { if (e_data.dof_prepare_sh == NULL) { - e_data.dof_prepare_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, - "#define PREPARE\n"); - - e_data.dof_downsample_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, - "#define DOWNSAMPLE\n"); + char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_workbench_effect_dof_frag_glsl); + e_data.dof_prepare_sh = DRW_shader_create_fullscreen(frag, "#define PREPARE\n"); + e_data.dof_downsample_sh = DRW_shader_create_fullscreen(frag, "#define DOWNSAMPLE\n"); #if 0 /* TODO(fclem) finish COC min_max optimization */ - e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, + e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(frag, "#define FLATTEN_VERTICAL\n"); - - e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, + e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(frag, "#define FLATTEN_HORIZONTAL\n"); - - e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, + e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(frag, "#define DILATE_VERTICAL\n"); - - e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, + e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(frag, "#define DILATE_HORIZONTAL\n"); #endif - e_data.dof_blur1_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, - "#define BLUR1\n"); - - e_data.dof_blur2_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, - "#define BLUR2\n"); - - e_data.dof_resolve_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl, - "#define RESOLVE\n"); + e_data.dof_blur1_sh = DRW_shader_create_fullscreen(frag, "#define BLUR1\n"); + e_data.dof_blur2_sh = DRW_shader_create_fullscreen(frag, "#define BLUR2\n"); + e_data.dof_resolve_sh = DRW_shader_create_fullscreen(frag, "#define RESOLVE\n"); + MEM_freeN(frag); } *prepare_sh = e_data.dof_prepare_sh; diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c index 39aa721a41c..5fd8229304a 100644 --- a/source/blender/draw/engines/workbench/workbench_transparent.c +++ b/source/blender/draw/engines/workbench/workbench_transparent.c @@ -67,7 +67,7 @@ void workbench_transparent_engine_init(WORKBENCH_Data *data) static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp) { - DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo); + DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo); DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false); if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) { @@ -78,8 +78,8 @@ static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd, struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture; const bool use_spec = workbench_is_specular_highlight_enabled(wpd); spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx; - DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx); - DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx); + DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx); + DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx); } } @@ -116,20 +116,20 @@ void workbench_transparent_cache_init(WORKBENCH_Data *data) workbench_transparent_lighting_uniforms(wpd, grp); wpd->prepass[transp][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr); + DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */ sh = workbench_shader_transparent_image_get(wpd, hair, false); wpd->prepass[transp][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr); + DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ workbench_transparent_lighting_uniforms(wpd, grp); sh = workbench_shader_transparent_image_get(wpd, hair, true); wpd->prepass[transp][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass); - DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr); + DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr); DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */ workbench_transparent_lighting_uniforms(wpd, grp); } diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index d3585b02b7d..b002f68e4d2 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -221,10 +221,7 @@ struct GPUShader *DRW_shader_create_with_transform_feedback(const char *vert, const eGPUShaderTFBType prim_type, const char **varying_names, const int varying_count); -struct GPUShader *DRW_shader_create_2d(const char *frag, const char *defines); -struct GPUShader *DRW_shader_create_3d(const char *frag, const char *defines); struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines); -struct GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig slot); struct GPUMaterial *DRW_shader_find_from_world(struct World *wo, const void *engine_type, const int options, @@ -235,6 +232,7 @@ struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma, bool deferred); struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, struct World *wo, + struct bNodeTree *ntree, const void *engine_type, const int options, const bool is_volume_shader, @@ -245,6 +243,7 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, bool deferred); struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, struct Material *ma, + struct bNodeTree *ntree, const void *engine_type, const int options, const bool is_volume_shader, @@ -376,6 +375,8 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, DRWPass *pass, struct GPUVertBuf *tf_target); +void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material); + /* return final visibility */ typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data); @@ -471,18 +472,15 @@ void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup, void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex); -void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup, - const char *name, - const struct GPUTexture *tex); -void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, - const char *name, - const struct GPUUniformBuffer *ubo); -void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup, - const char *name, - const struct GPUUniformBuffer *ubo); void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, struct GPUTexture **tex); +void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, + const char *name, + const struct GPUUniformBuffer *ubo); +void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup, + const char *name, + struct GPUUniformBuffer **ubo); void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, @@ -541,6 +539,8 @@ bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup); /* Passes */ DRWPass *DRW_pass_create(const char *name, DRWState state); +DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state); +void DRW_pass_link(DRWPass *first, DRWPass *second); /* TODO Replace with passes inheritance. */ void DRW_pass_state_set(DRWPass *pass, DRWState state); void DRW_pass_state_add(DRWPass *pass, DRWState state); @@ -554,6 +554,8 @@ void DRW_pass_sort_shgroup_reverse(DRWPass *pass); bool DRW_pass_is_empty(DRWPass *pass); #define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state)) +#define DRW_PASS_INSTANCE_CREATE(pass, original, state) \ + (pass = DRW_pass_create_instance(#pass, (original), state)) /* Views */ DRWView *DRW_view_create(const float viewmat[4][4], @@ -707,6 +709,8 @@ typedef struct DRWContextState { struct Depsgraph *depsgraph; + struct TaskGraph *task_graph; + eObjectMode object_mode; eGPUShaderConfig sh_cfg; diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 23d0d74534d..c23ea3d7c82 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -3534,13 +3534,15 @@ void drw_batch_cache_generate_requested(Object *ob) struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); switch (ob->type) { case OB_MESH: - DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide); + DRW_mesh_batch_cache_create_requested( + DST.task_graph, ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide); break; case OB_CURVE: case OB_FONT: case OB_SURF: if (mesh_eval) { - DRW_mesh_batch_cache_create_requested(ob, mesh_eval, scene, is_paint_mode, use_hide); + DRW_mesh_batch_cache_create_requested( + DST.task_graph, ob, mesh_eval, scene, is_paint_mode, use_hide); } DRW_curve_batch_cache_create_requested(ob); break; diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index b2fea957227..f203c2ff1ea 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -23,6 +23,8 @@ #ifndef __DRAW_CACHE_EXTRACT_H__ #define __DRAW_CACHE_EXTRACT_H__ +struct TaskGraph; + /* Vertex Group Selection and display options */ typedef struct DRW_MeshWeightState { int defgroup_active; @@ -249,7 +251,8 @@ typedef struct MeshBatchCache { bool no_loose_wire; } MeshBatchCache; -void mesh_buffer_cache_create_requested(MeshBatchCache *cache, +void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, + MeshBatchCache *cache, MeshBufferCache mbc, Mesh *me, const bool is_editmode, diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index cbb5f5f06ff..0fd6bf54856 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -134,15 +134,12 @@ typedef struct MeshRenderData { float (*poly_normals)[3]; int *lverts, *ledges; } MeshRenderData; - static MeshRenderData *mesh_render_data_create(Mesh *me, const bool is_editmode, const bool is_paint_mode, const float obmat[4][4], const bool do_final, const bool do_uvedit, - const eMRIterType iter_type, - const eMRDataType data_flag, const DRW_MeshCDMask *UNUSED(cd_used), const ToolSettings *ts) { @@ -152,9 +149,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, copy_m4_m4(mr->obmat, obmat); - const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0; - const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI; - if (is_editmode) { BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final); mr->bm = me->edit_mesh->bm; @@ -244,7 +238,32 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX); mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX); mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX); + } + else { + /* BMesh */ + BMesh *bm = mr->bm; + + mr->vert_len = bm->totvert; + mr->edge_len = bm->totedge; + mr->loop_len = bm->totloop; + mr->poly_len = bm->totface; + mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len); + } + return mr; +} + +/* Part of the creation of the MeshRenderData that happens in a thread. */ +static void mesh_render_data_update(MeshRenderData *mr, + const eMRIterType iter_type, + const eMRDataType data_flag) +{ + Mesh *me = mr->me; + const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0; + const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI; + + if (mr->extract_type != MR_EXTRACT_BMESH) { + /* Mesh */ if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) { mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__); BKE_mesh_calc_normals_poly((MVert *)mr->mvert, @@ -323,13 +342,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, else { /* BMesh */ BMesh *bm = mr->bm; - - mr->vert_len = bm->totvert; - mr->edge_len = bm->totedge; - mr->loop_len = bm->totloop; - mr->poly_len = bm->totface; - mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len); - if (data_flag & MR_DATA_POLY_NOR) { /* Use bmface->no instead. */ } @@ -394,7 +406,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2; } } - return mr; } static void mesh_render_data_free(MeshRenderData *mr) @@ -742,46 +753,15 @@ static const MeshExtract extract_lines = { 0, false, }; - /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Loose Edges Indices +/** \name Extract Loose Edges Sub Buffer * \{ */ -static void *extract_lines_loose_init(const MeshRenderData *UNUSED(mr), void *UNUSED(buf)) -{ - return NULL; -} - -static void extract_lines_loose_ledge_mesh(const MeshRenderData *UNUSED(mr), - int UNUSED(e), - const MEdge *UNUSED(medge), - void *UNUSED(elb)) -{ - /* This function is intentionally empty. The existence of this functions ensures that - * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See - * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This - * field we use in the `extract_lines_loose_finish` function to create a subrange from the - * `ibo.lines`. */ -} - -static void extract_lines_loose_ledge_bmesh(const MeshRenderData *UNUSED(mr), - int UNUSED(e), - BMEdge *UNUSED(eed), - void *UNUSED(elb)) -{ - /* This function is intentionally empty. The existence of this functions ensures that - * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See - * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This - * field we use in the `extract_lines_loose_finish` function to create a subrange from the - * `ibo.lines`. */ -} - -static void extract_lines_loose_finish(const MeshRenderData *mr, - void *UNUSED(ibo), - void *UNUSED(elb)) +static void extract_lines_loose_subbuffer(const MeshRenderData *mr) { + BLI_assert(mr->cache->final.ibo.lines); /* Multiply by 2 because these are edges indices. */ const int start = mr->edge_len * 2; const int len = mr->edge_loose_len * 2; @@ -790,17 +770,24 @@ static void extract_lines_loose_finish(const MeshRenderData *mr, mr->cache->no_loose_wire = (len == 0); } -static const MeshExtract extract_lines_loose = { - extract_lines_loose_init, - NULL, - NULL, +static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void *ibo, void *elb) +{ + GPU_indexbuf_build_in_place(elb, ibo); + extract_lines_loose_subbuffer(mr); + MEM_freeN(elb); +} + +static const MeshExtract extract_lines_with_lines_loose = { + extract_lines_init, NULL, NULL, - extract_lines_loose_ledge_bmesh, - extract_lines_loose_ledge_mesh, + extract_lines_loop_bmesh, + extract_lines_loop_mesh, + extract_lines_ledge_bmesh, + extract_lines_ledge_mesh, NULL, NULL, - extract_lines_loose_finish, + extract_lines_with_lines_loose_finish, 0, false, }; @@ -1716,8 +1703,8 @@ static void extract_lnor_hq_loop_mesh( } /* Flag for paint mode overlay. - * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint - * mode it will use the unmapped data to draw the wireframe. */ + * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In + * paint mode it will use the unmapped data to draw the wireframe. */ if (mpoly->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) { @@ -1795,8 +1782,8 @@ static void extract_lnor_loop_mesh( } /* Flag for paint mode overlay. - * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint - * mode it will use the unmapped data to draw the wireframe. */ + * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In + * paint mode it will use the unmapped data to draw the wireframe. */ if (mpoly->flag & ME_HIDE || (mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) && mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) { @@ -2162,10 +2149,10 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) GPUVertFormat format = {0}; GPU_vertformat_deinterleave(&format); - CustomData *cd_ldata = &mr->me->ldata; + CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata; uint32_t vcol_layers = mr->cache->cd_used.vcol; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < MAX_MCOL; i++) { if (vcol_layers & (1 << i)) { char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i); @@ -2197,14 +2184,32 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf) } gpuMeshVcol; gpuMeshVcol *vcol_data = (gpuMeshVcol *)vbo->data; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < MAX_MCOL; i++) { if (vcol_layers & (1 << i)) { - MLoopCol *mcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i); - for (int l = 0; l < mr->loop_len; l++, mcol++, vcol_data++) { - vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]); - vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]); - vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]); - vcol_data->a = unit_float_to_ushort_clamp(mcol->a * (1.0f / 255.0f)); + if (mr->extract_type == MR_EXTRACT_BMESH) { + int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i); + BMIter f_iter, l_iter; + BMFace *efa; + BMLoop *loop; + BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) { + const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs); + vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); + vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); + vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); + vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); + vcol_data++; + } + } + } + else { + const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i); + for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) { + vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); + vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); + vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); + vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); + } } } } @@ -4522,10 +4527,14 @@ static const MeshExtract extract_fdot_idx = { /** \} */ /* ---------------------------------------------------------------------- */ -/** \name Extract Loop +/** \name ExtractTaskData * \{ */ +typedef struct ExtractUserData { + void *user_data; +} ExtractUserData; typedef struct ExtractTaskData { + void *next, *prev; const MeshRenderData *mr; const MeshExtract *extract; eMRIterType iter_type; @@ -4533,9 +4542,16 @@ typedef struct ExtractTaskData { /** Decremented each time a task is finished. */ int32_t *task_counter; void *buf; - void *user_data; + ExtractUserData *user_data; } ExtractTaskData; +static void extract_task_data_free(void *data) +{ + ExtractTaskData *task_data = data; + MEM_SAFE_FREE(task_data->user_data); + MEM_freeN(task_data); +} + BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, const eMRIterType iter_type, int start, @@ -4612,31 +4628,184 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, } } -static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata) +static void extract_init(ExtractTaskData *data) { - ExtractTaskData *data = taskdata; - mesh_extract_iter( - data->mr, data->iter_type, data->start, data->end, data->extract, data->user_data); + data->user_data->user_data = data->extract->init(data->mr, data->buf); +} + +static void extract_run(void *__restrict taskdata) +{ + ExtractTaskData *data = (ExtractTaskData *)taskdata; + mesh_extract_iter(data->mr, + data->iter_type, + data->start, + data->end, + data->extract, + data->user_data->user_data); /* If this is the last task, we do the finish function. */ int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1); if (remainin_tasks == 0 && data->extract->finish != NULL) { - data->extract->finish(data->mr, data->buf, data->user_data); + data->extract->finish(data->mr, data->buf, data->user_data->user_data); + } +} + +static void extract_init_and_run(void *__restrict taskdata) +{ + extract_init((ExtractTaskData *)taskdata); + extract_run(taskdata); +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Task Node - Update Mesh Render Data + * \{ */ +typedef struct MeshRenderDataUpdateTaskData { + MeshRenderData *mr; + eMRIterType iter_type; + eMRDataType data_flag; +} MeshRenderDataUpdateTaskData; + +static void mesh_render_data_update_task_data_free(MeshRenderDataUpdateTaskData *taskdata) +{ + BLI_assert(taskdata); + mesh_render_data_free(taskdata->mr); + MEM_freeN(taskdata); +} + +static void mesh_extract_render_data_node_exec(void *__restrict task_data) +{ + MeshRenderDataUpdateTaskData *update_task_data = task_data; + mesh_render_data_update( + update_task_data->mr, update_task_data->iter_type, update_task_data->data_flag); +} + +static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph, + MeshRenderData *mr, + const eMRIterType iter_type, + const eMRDataType data_flag) +{ + MeshRenderDataUpdateTaskData *task_data = MEM_mallocN(sizeof(MeshRenderDataUpdateTaskData), + __func__); + task_data->mr = mr; + task_data->iter_type = iter_type; + task_data->data_flag = data_flag; + + struct TaskNode *task_node = BLI_task_graph_node_create( + task_graph, + mesh_extract_render_data_node_exec, + task_data, + (TaskGraphNodeFreeFunction)mesh_render_data_update_task_data_free); + return task_node; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Task Node - Extract Single Threaded + * \{ */ +typedef struct ExtractSingleThreadedTaskData { + ListBase task_datas; +} ExtractSingleThreadedTaskData; + +static void extract_single_threaded_task_data_free(ExtractSingleThreadedTaskData *taskdata) +{ + BLI_assert(taskdata); + LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) { + extract_task_data_free(td); + } + BLI_listbase_clear(&taskdata->task_datas); + MEM_freeN(taskdata); +} + +static void extract_single_threaded_task_node_exec(void *__restrict task_data) +{ + ExtractSingleThreadedTaskData *extract_task_data = task_data; + LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) { + extract_init_and_run(td); + } +} + +static struct TaskNode *extract_single_threaded_task_node_create( + struct TaskGraph *task_graph, ExtractSingleThreadedTaskData *task_data) +{ + struct TaskNode *task_node = BLI_task_graph_node_create( + task_graph, + extract_single_threaded_task_node_exec, + task_data, + (TaskGraphNodeFreeFunction)extract_single_threaded_task_data_free); + return task_node; +} + +/** \} */ + +/* ---------------------------------------------------------------------- */ +/** \name Task Node - UserData Initializer + * \{ */ +typedef struct UserDataInitTaskData { + ListBase task_datas; + int32_t *task_counters; + +} UserDataInitTaskData; + +static void user_data_init_task_data_free(UserDataInitTaskData *taskdata) +{ + BLI_assert(taskdata); + LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) { + extract_task_data_free(td); + } + BLI_listbase_clear(&taskdata->task_datas); + MEM_SAFE_FREE(taskdata->task_counters); + MEM_freeN(taskdata); +} + +static void user_data_init_task_data_exec(void *__restrict task_data) +{ + UserDataInitTaskData *extract_task_data = task_data; + LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) { + extract_init(td); } } -static void extract_range_task_create( - TaskPool *task_pool, ExtractTaskData *taskdata, const eMRIterType type, int start, int length) +static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph, + UserDataInitTaskData *task_data) +{ + struct TaskNode *task_node = BLI_task_graph_node_create( + task_graph, + user_data_init_task_data_exec, + task_data, + (TaskGraphNodeFreeFunction)user_data_init_task_data_free); + return task_node; +} + +/** \} */ +/* ---------------------------------------------------------------------- */ +/** \name Extract Loop + * \{ */ + +static void extract_range_task_create(struct TaskGraph *task_graph, + struct TaskNode *task_node_user_data_init, + ExtractTaskData *taskdata, + const eMRIterType type, + int start, + int length) { taskdata = MEM_dupallocN(taskdata); atomic_add_and_fetch_int32(taskdata->task_counter, 1); taskdata->iter_type = type; taskdata->start = start; taskdata->end = start + length; - BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL); + struct TaskNode *task_node = BLI_task_graph_node_create( + task_graph, extract_run, taskdata, MEM_freeN); + BLI_task_graph_edge_create(task_node_user_data_init, task_node); } -static void extract_task_create(TaskPool *task_pool, +static void extract_task_create(struct TaskGraph *task_graph, + struct TaskNode *task_node_mesh_render_data, + struct TaskNode *task_node_user_data_init, + ListBase *single_threaded_task_datas, + ListBase *user_data_init_task_datas, const Scene *scene, const MeshRenderData *mr, const MeshExtract *extract, @@ -4654,58 +4823,75 @@ static void extract_task_create(TaskPool *task_pool, /* Divide extraction of the VBO/IBO into sensible chunks of works. */ ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), "ExtractTaskData"); + taskdata->next = NULL; + taskdata->prev = NULL; taskdata->mr = mr; taskdata->extract = extract; taskdata->buf = buf; - taskdata->user_data = extract->init(mr, buf); + + /* ExtractUserData is shared between the iterations as it holds counters to detect if the + * extraction is finished. To make sure the duplication of the userdata does not create a new + * instance of the counters we allocate the userdata in its own container. + * + * This structure makes sure that when extract_init is called, that the user data of all + * iterations are updated. */ + taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__); taskdata->iter_type = mesh_extract_iter_type(extract); taskdata->task_counter = task_counter; taskdata->start = 0; taskdata->end = INT_MAX; /* Simple heuristic. */ - const bool use_thread = (mr->loop_len + mr->loop_loose_len) > 8192; + const int chunk_size = 8192; + const bool use_thread = (mr->loop_len + mr->loop_loose_len) > chunk_size; if (use_thread && extract->use_threading) { + /* Divide task into sensible chunks. */ - const int chunk_size = 8192; if (taskdata->iter_type & MR_ITER_LOOPTRI) { for (int i = 0; i < mr->tri_len; i += chunk_size) { - extract_range_task_create(task_pool, taskdata, MR_ITER_LOOPTRI, i, chunk_size); + extract_range_task_create( + task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size); } } if (taskdata->iter_type & MR_ITER_LOOP) { for (int i = 0; i < mr->poly_len; i += chunk_size) { - extract_range_task_create(task_pool, taskdata, MR_ITER_LOOP, i, chunk_size); + extract_range_task_create( + task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOP, i, chunk_size); } } if (taskdata->iter_type & MR_ITER_LEDGE) { for (int i = 0; i < mr->edge_loose_len; i += chunk_size) { - extract_range_task_create(task_pool, taskdata, MR_ITER_LEDGE, i, chunk_size); + extract_range_task_create( + task_graph, task_node_user_data_init, taskdata, MR_ITER_LEDGE, i, chunk_size); } } if (taskdata->iter_type & MR_ITER_LVERT) { for (int i = 0; i < mr->vert_loose_len; i += chunk_size) { - extract_range_task_create(task_pool, taskdata, MR_ITER_LVERT, i, chunk_size); + extract_range_task_create( + task_graph, task_node_user_data_init, taskdata, MR_ITER_LVERT, i, chunk_size); } } - MEM_freeN(taskdata); + BLI_addtail(user_data_init_task_datas, taskdata); } else if (use_thread) { /* One task for the whole VBO. */ (*task_counter)++; - BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL); + struct TaskNode *one_task = BLI_task_graph_node_create( + task_graph, extract_init_and_run, taskdata, extract_task_data_free); + BLI_task_graph_edge_create(task_node_mesh_render_data, one_task); } else { /* Single threaded extraction. */ (*task_counter)++; - extract_run(NULL, taskdata); - MEM_freeN(taskdata); + BLI_addtail(single_threaded_task_datas, taskdata); } } -void mesh_buffer_cache_create_requested(MeshBatchCache *cache, +void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, + MeshBatchCache *cache, MeshBufferCache mbc, Mesh *me, + const bool is_editmode, const bool is_paint_mode, const float obmat[4][4], @@ -4717,9 +4903,41 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, const ToolSettings *ts, const bool use_hide) { + /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph. + * This sub-graph starts with an extract_render_data_node. This fills/converts the required data + * from Mesh. + * + * Small extractions and extractions that can't be multi-threaded are grouped in a single + * `extract_single_threaded_task_node`. + * + * Other extractions will create a node for each loop exceeding 8192 items. these nodes are + * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the userdata + * needed for the extraction based on the data extracted from the mesh. counters are used to + * check if the finalize of a task has to be called. + * + * Mesh extraction sub graph + * + * +----------------------+ + * +-----> | extract_task1_loop_1 | + * | +----------------------+ + * +------------------+ +----------------------+ +----------------------+ + * | mesh_render_data | --> | | --> | extract_task1_loop_2 | + * +------------------+ | | +----------------------+ + * | | | +----------------------+ + * | | user_data_init | --> | extract_task2_loop_1 | + * v | | +----------------------+ + * +------------------+ | | +----------------------+ + * | single_threaded | | | --> | extract_task2_loop_2 | + * +------------------+ +----------------------+ +----------------------+ + * | +----------------------+ + * +-----> | extract_task2_loop_3 | + * +----------------------+ + */ eMRIterType iter_flag = 0; eMRDataType data_flag = 0; + const bool do_lines_loose_subbuffer = mbc.ibo.lines_loose != NULL; + #define TEST_ASSIGN(type, type_lowercase, name) \ do { \ if (DRW_TEST_ASSIGN_##type(mbc.type_lowercase.name)) { \ @@ -4757,7 +4975,6 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, TEST_ASSIGN(IBO, ibo, fdots); TEST_ASSIGN(IBO, ibo, lines_paint_mask); TEST_ASSIGN(IBO, ibo, lines_adjacency); - TEST_ASSIGN(IBO, ibo, lines_loose); TEST_ASSIGN(IBO, ibo, edituv_tris); TEST_ASSIGN(IBO, ibo, edituv_lines); TEST_ASSIGN(IBO, ibo, edituv_points); @@ -4769,16 +4986,8 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, double rdata_start = PIL_check_seconds_timer(); #endif - MeshRenderData *mr = mesh_render_data_create(me, - is_editmode, - is_paint_mode, - obmat, - do_final, - do_uvedit, - iter_flag, - data_flag, - cd_layer_used, - ts); + MeshRenderData *mr = mesh_render_data_create( + me, is_editmode, is_paint_mode, obmat, do_final, do_uvedit, cd_layer_used, ts); mr->cache = cache; /* HACK */ mr->use_hide = use_hide; mr->use_subsurf_fdots = use_subsurf_fdots; @@ -4788,20 +4997,32 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, double rdata_end = PIL_check_seconds_timer(); #endif - TaskPool *task_pool; - - /* Create a suspended pool as the finalize method could be called too early. - * See `extract_run`. */ - task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH); - size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t); int32_t *task_counters = MEM_callocN(counters_size, __func__); int counter_used = 0; + struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create( + task_graph, mr, iter_flag, data_flag); + ExtractSingleThreadedTaskData *single_threaded_task_data = MEM_callocN( + sizeof(ExtractSingleThreadedTaskData), __func__); + UserDataInitTaskData *user_data_init_task_data = MEM_callocN(sizeof(UserDataInitTaskData), + __func__); + user_data_init_task_data->task_counters = task_counters; + struct TaskNode *task_node_user_data_init = user_data_init_task_node_create( + task_graph, user_data_init_task_data); + #define EXTRACT(buf, name) \ if (mbc.buf.name) { \ - extract_task_create( \ - task_pool, scene, mr, &extract_##name, mbc.buf.name, &task_counters[counter_used++]); \ + extract_task_create(task_graph, \ + task_node_mesh_render_data, \ + task_node_user_data_init, \ + &single_threaded_task_data->task_datas, \ + &user_data_init_task_data->task_datas, \ + scene, \ + mr, \ + &extract_##name, \ + mbc.buf.name, \ + &task_counters[counter_used++]); \ } \ ((void)0) @@ -4829,7 +5050,33 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, EXTRACT(vbo, skin_roots); EXTRACT(ibo, tris); - EXTRACT(ibo, lines); + if (mbc.ibo.lines) { + /* When `lines` and `lines_loose` are requested, schedule lines extraction that also creates + * the `lines_loose` sub-buffer. */ + const MeshExtract *lines_extractor = do_lines_loose_subbuffer ? + &extract_lines_with_lines_loose : + &extract_lines; + extract_task_create(task_graph, + task_node_mesh_render_data, + task_node_user_data_init, + &single_threaded_task_data->task_datas, + &user_data_init_task_data->task_datas, + scene, + mr, + lines_extractor, + mbc.ibo.lines, + &task_counters[counter_used++]); + } + else { + if (do_lines_loose_subbuffer) { + /* When `lines_loose` is requested without `lines` we can create the sub-buffer on the fly as + * the `lines` buffer should then already be up-to-date. + * (see `DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)` in + * `DRW_mesh_batch_cache_create_requested`). + */ + extract_lines_loose_subbuffer(mr); + } + } EXTRACT(ibo, points); EXTRACT(ibo, fdots); EXTRACT(ibo, lines_paint_mask); @@ -4839,27 +5086,29 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, EXTRACT(ibo, edituv_points); EXTRACT(ibo, edituv_fdots); - /* TODO(fclem) Ideally, we should have one global pool for all - * objects and wait for finish only before drawing when buffers - * need to be ready. */ - BLI_task_pool_work_and_wait(task_pool); - - /* The next task(s) rely on the result of the tasks above. */ + /* Only create the edge when there are user datas that needs to be inited. + * The task is still part of the graph so the task_data will be freed when the graph is freed. + */ + if (!BLI_listbase_is_empty(&user_data_init_task_data->task_datas)) { + BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init); + } - /* The `lines_loose` is a sub buffer from `ibo.lines`. - * We schedule it here due to potential synchronization issues.*/ - EXTRACT(ibo, lines_loose); + if (!BLI_listbase_is_empty(&single_threaded_task_data->task_datas)) { + struct TaskNode *task_node = extract_single_threaded_task_node_create( + task_graph, single_threaded_task_data); + BLI_task_graph_edge_create(task_node_mesh_render_data, task_node); + } + else { + extract_single_threaded_task_data_free(single_threaded_task_data); + } - BLI_task_pool_work_and_wait(task_pool); + /* Trigger the sub-graph for this mesh. */ + BLI_task_graph_node_push_work(task_node_mesh_render_data); #undef EXTRACT - BLI_task_pool_free(task_pool); - MEM_freeN(task_counters); - - mesh_render_data_free(mr); - #ifdef DEBUG_TIME + BLI_task_graph_work_and_wait(task_graph); double end = PIL_check_seconds_timer(); static double avg = 0; diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index daa46252331..80649143537 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -31,6 +31,7 @@ struct ListBase; struct ModifierData; struct PTCacheEdit; struct ParticleSystem; +struct TaskGraph; struct Curve; struct Hair; @@ -150,7 +151,8 @@ int DRW_volume_material_count_get(struct Volume *volume); struct GPUBatch *DRW_volume_batch_cache_get_wireframes_face(struct Volume *volume); /* Mesh */ -void DRW_mesh_batch_cache_create_requested(struct Object *ob, +void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, + struct Object *ob, struct Mesh *me, const struct Scene *scene, const bool is_paint_mode, diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index ee148e0934d..b4974330043 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -102,6 +102,7 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra) cache->is_dirty = true; cache->cache_frame = cfra; + return cache; } @@ -385,7 +386,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr .vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */ .tri_len = 0, }; - BKE_gpencil_visible_stroke_iter(ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra); + BKE_gpencil_visible_stroke_iter( + NULL, ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra); /* Create VBOs. */ GPUVertFormat *format = gpencil_stroke_format(); @@ -401,7 +403,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len); /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra); + BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra); /* Mark last 2 verts as invalid. */ for (int i = 0; i < 2; i++) { @@ -475,7 +477,7 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob) /* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */ bool do_onion = true; - BKE_gpencil_visible_stroke_iter(ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra); + BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra); GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo); @@ -724,7 +726,8 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in iter.verts = (gpEditVert *)cache->edit_vbo->data; /* Fill buffers with data. */ - BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra); + BKE_gpencil_visible_stroke_iter( + NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra); /* Create the batches */ cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, NULL); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 237c7bddfad..99e285a18f1 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -33,6 +33,7 @@ #include "BLI_math_bits.h" #include "BLI_math_vector.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BLI_utildefines.h" #include "DNA_mesh_types.h" @@ -1019,9 +1020,14 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) } /* Can be called for any surface type. Mesh *me is the final mesh. */ -void DRW_mesh_batch_cache_create_requested( - Object *ob, Mesh *me, const Scene *scene, const bool is_paint_mode, const bool use_hide) -{ +void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, + Object *ob, + Mesh *me, + const Scene *scene, + const bool is_paint_mode, + const bool use_hide) +{ + BLI_assert(task_graph); GPUIndexBuf **saved_elem_ranges = NULL; const ToolSettings *ts = NULL; if (scene) { @@ -1378,7 +1384,8 @@ void DRW_mesh_batch_cache_create_requested( false; if (do_uvcage) { - mesh_buffer_cache_create_requested(cache, + mesh_buffer_cache_create_requested(task_graph, + cache, cache->uv_cage, me, is_editmode, @@ -1394,7 +1401,8 @@ void DRW_mesh_batch_cache_create_requested( } if (do_cage) { - mesh_buffer_cache_create_requested(cache, + mesh_buffer_cache_create_requested(task_graph, + cache, cache->cage, me, is_editmode, @@ -1409,7 +1417,8 @@ void DRW_mesh_batch_cache_create_requested( true); } - mesh_buffer_cache_create_requested(cache, + mesh_buffer_cache_create_requested(task_graph, + cache, cache->final, me, is_editmode, @@ -1422,10 +1431,12 @@ void DRW_mesh_batch_cache_create_requested( scene, ts, use_hide); - #ifdef DEBUG check: /* Make sure all requested batches have been setup. */ + /* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and + * additional looping.*/ + BLI_task_graph_work_and_wait(task_graph); for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0)); } diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index f14cdc0dbde..656d72b2808 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -172,23 +172,11 @@ bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis); /* This creates a shading group with display hairs. * The draw call is already added by this function, just add additional uniforms. */ -struct DRWShadingGroup *DRW_shgroup_hair_create(struct Object *object, - struct ParticleSystem *psys, - struct ModifierData *md, - struct DRWPass *hair_pass, - struct GPUShader *shader); - struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object, struct ParticleSystem *psys, struct ModifierData *md, struct DRWShadingGroup *shgrp); -struct DRWShadingGroup *DRW_shgroup_material_hair_create(struct Object *object, - struct ParticleSystem *psys, - struct ModifierData *md, - struct DRWPass *hair_pass, - struct GPUMaterial *material); - void DRW_hair_init(void); void DRW_hair_update(void); void DRW_hair_free(void); diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 27de7cc1c7c..2fdaf0d5345 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -124,13 +124,10 @@ void DRW_hair_init(void) } } -static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, - ParticleSystem *psys, - ModifierData *md, - DRWPass *hair_pass, - DRWShadingGroup *shgrp_parent, - struct GPUMaterial *gpu_mat, - GPUShader *gpu_shader) +DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, + ParticleSystem *psys, + ModifierData *md, + DRWShadingGroup *shgrp_parent) { /* TODO(fclem): Pass the scene as parameter */ const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -154,24 +151,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res); } - DRWShadingGroup *shgrp; - if (shgrp_parent) { - shgrp = DRW_shgroup_create_sub(shgrp_parent); - } - else if (gpu_mat) { - shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass); - } - else if (gpu_shader) { - shgrp = DRW_shgroup_create(gpu_shader, hair_pass); - } - else { - shgrp = NULL; - BLI_assert(0); - } - - if (shgrp == NULL) { - return NULL; - } + DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent); /* TODO optimize this. Only bind the ones GPUMaterial needs. */ for (int i = 0; i < hair_cache->num_uv_layers; i++) { @@ -284,29 +264,6 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object, return shgrp; } -DRWShadingGroup *DRW_shgroup_hair_create( - Object *object, ParticleSystem *psys, ModifierData *md, DRWPass *hair_pass, GPUShader *shader) -{ - return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, NULL, shader); -} - -DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object, - ParticleSystem *psys, - ModifierData *md, - DRWShadingGroup *shgrp) -{ - return drw_shgroup_create_hair_procedural_ex(object, psys, md, NULL, shgrp, NULL, NULL); -} - -DRWShadingGroup *DRW_shgroup_material_hair_create(Object *object, - ParticleSystem *psys, - ModifierData *md, - DRWPass *hair_pass, - struct GPUMaterial *material) -{ - return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, material, NULL); -} - void DRW_hair_update(void) { #ifndef USE_TRANSFORM_FEEDBACK diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index bdef6d50db8..08c6a0e8da8 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -27,6 +27,7 @@ #include "BLI_memblock.h" #include "BLI_rect.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "BLF_api.h" @@ -115,17 +116,6 @@ static ListBase DRW_engines = {NULL, NULL}; static void drw_state_prepare_clean_for_draw(DRWManager *dst) { memset(dst, 0x0, offsetof(DRWManager, gl_context)); - - /* Maybe not the best place for this. */ - if (!DST.uniform_names.buffer) { - DST.uniform_names.buffer = MEM_callocN(DRW_UNIFORM_BUFFER_NAME, "Name Buffer"); - DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME; - } - else if (DST.uniform_names.buffer_len > DRW_UNIFORM_BUFFER_NAME) { - DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DRW_UNIFORM_BUFFER_NAME); - DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME; - } - DST.uniform_names.buffer_ofs = 0; } /* This function is used to reset draw manager to a state @@ -140,6 +130,23 @@ static void drw_state_ensure_not_reused(DRWManager *dst) #endif /* -------------------------------------------------------------------- */ +/** \name Threading + * \{ */ +static void drw_task_graph_init(void) +{ + BLI_assert(DST.task_graph == NULL); + DST.task_graph = BLI_task_graph_create(); +} + +static void drw_task_graph_deinit(void) +{ + BLI_task_graph_work_and_wait(DST.task_graph); + BLI_task_graph_free(DST.task_graph); + DST.task_graph = NULL; +} +/* \} */ + +/* -------------------------------------------------------------------- */ /** \name Settings * \{ */ @@ -588,9 +595,6 @@ static void drw_viewport_var_init(void) ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d); } - /* Alloc array of texture reference. */ - memset(&DST.RST, 0x0, sizeof(DST.RST)); - if (G_draw.view_ubo == NULL) { G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL); } @@ -1428,6 +1432,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, /* reuse if caller sets */ .evil_C = DST.draw_ctx.evil_C, }; + drw_task_graph_init(); drw_context_state_init(); drw_viewport_var_init(); @@ -1492,6 +1497,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, #endif } + drw_task_graph_deinit(); DRW_stats_begin(); GPU_framebuffer_bind(DST.default_framebuffer); @@ -1772,7 +1778,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph) DST.options.is_image_render = true; DST.options.is_scene_render = true; DST.options.draw_background = scene->r.alphamode == R_ADDSKY; - DST.draw_ctx = (DRWContextState){ .scene = scene, .view_layer = view_layer, @@ -1857,9 +1862,9 @@ void DRW_render_object_iter( void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph)) { const DRWContextState *draw_ctx = DRW_context_state_get(); - DRW_hair_init(); + drw_task_graph_init(); const int object_type_exclude_viewport = draw_ctx->v3d ? draw_ctx->v3d->object_type_exclude_viewport : 0; @@ -1882,6 +1887,7 @@ void DRW_render_object_iter( DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; drw_duplidata_free(); + drw_task_graph_deinit(); } /* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired). @@ -2053,7 +2059,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, DST.viewport = viewport; DST.options.is_select = true; - + drw_task_graph_init(); /* Get list of enabled engines */ if (use_obedit) { drw_engines_enable_overlays(); @@ -2163,6 +2169,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, } drw_duplidata_free(); + drw_task_graph_deinit(); drw_engines_cache_finish(); DRW_render_instance_buffer_finish(); @@ -2243,7 +2250,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, .engine_type = engine_type, .depsgraph = depsgraph, }; - + drw_task_graph_init(); drw_engines_data_validate(); /* Setup framebuffer */ @@ -2287,6 +2294,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, DRW_render_instance_buffer_finish(); } + drw_task_graph_deinit(); /* Start Drawing */ DRW_state_reset(); @@ -2376,7 +2384,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons .obact = OBACT(view_layer), .depsgraph = depsgraph, }; - + drw_task_graph_init(); drw_context_state_init(); /* Setup viewport */ @@ -2411,6 +2419,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_resource_buffer_finish(DST.vmempool); #endif } + drw_task_graph_deinit(); /* Start Drawing */ DRW_state_reset(); @@ -2474,8 +2483,10 @@ void DRW_draw_depth_object( else { batch = DRW_mesh_batch_cache_get_surface(me); } - - DRW_mesh_batch_cache_create_requested(object, me, scene, false, true); + struct TaskGraph *task_graph = BLI_task_graph_create(); + DRW_mesh_batch_cache_create_requested(task_graph, object, me, scene, false, true); + BLI_task_graph_work_and_wait(task_graph); + BLI_task_graph_free(task_graph); const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : GPU_SHADER_CFG_DEFAULT; @@ -2721,8 +2732,6 @@ void DRW_engines_free(void) DRW_TEXTURE_FREE_SAFE(G_draw.ramp); DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp); - MEM_SAFE_FREE(DST.uniform_names.buffer); - if (DST.draw_list) { GPU_draw_list_discard(DST.draw_list); } diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index f6d8179b193..733711a06da 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -31,6 +31,7 @@ #include "BLI_assert.h" #include "BLI_linklist.h" #include "BLI_memblock.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "GPU_batch.h" @@ -276,10 +277,9 @@ typedef enum { DRW_UNIFORM_FLOAT, DRW_UNIFORM_FLOAT_COPY, DRW_UNIFORM_TEXTURE, - DRW_UNIFORM_TEXTURE_PERSIST, DRW_UNIFORM_TEXTURE_REF, DRW_UNIFORM_BLOCK, - DRW_UNIFORM_BLOCK_PERSIST, + DRW_UNIFORM_BLOCK_REF, DRW_UNIFORM_TFEEDBACK_TARGET, /** Per drawcall uniforms/UBO */ DRW_UNIFORM_BLOCK_OBMATS, @@ -290,7 +290,6 @@ typedef enum { DRW_UNIFORM_BASE_INSTANCE, DRW_UNIFORM_MODEL_MATRIX, DRW_UNIFORM_MODEL_MATRIX_INVERSE, - DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX, /* WARNING: set DRWUniform->type * bit length accordingly. */ } DRWUniformType; @@ -299,15 +298,28 @@ struct DRWUniform { union { /* For reference or array/vector types. */ const void *pvalue; - /* Single values. */ + /* DRW_UNIFORM_TEXTURE */ + struct { + union { + GPUTexture *texture; + GPUTexture **texture_ref; + }; + eGPUSamplerState sampler_state; + }; + /* DRW_UNIFORM_BLOCK */ + union { + GPUUniformBuffer *block; + GPUUniformBuffer **block_ref; + }; + /* DRW_UNIFORM_FLOAT_COPY */ float fvalue[4]; + /* DRW_UNIFORM_INT_COPY */ int ivalue[4]; }; - int location; + int location; /* Use as binding point for textures and ubos. */ uint32_t type : 5; /* DRWUniformType */ uint32_t length : 5; /* cannot be more than 16 */ uint32_t arraysize : 5; /* cannot be more than 16 too */ - uint32_t name_ofs : 17; /* name offset in name buffer. */ }; struct DRWShadingGroup { @@ -342,6 +354,13 @@ struct DRWPass { DRWShadingGroup *last; } shgroups; + /* Draw the shgroups of this pass instead. + * This avoid duplicating drawcalls/shgroups + * for similar passes. */ + DRWPass *original; + /* Link list of additional passes to render. */ + DRWPass *next; + DRWResourceHandle handle; DRWState state; char name[MAX_PASS_NAME]; @@ -525,6 +544,8 @@ typedef struct DRWManager { uint select_id; #endif + struct TaskGraph *task_graph; + /* ---------- Nothing after this point is cleared after use ----------- */ /* gl_context serves as the offset for clearing only @@ -537,31 +558,11 @@ typedef struct DRWManager { GPUDrawList *draw_list; - /** GPU Resource State: Memory storage between drawing. */ - struct { - /* High end GPUs supports up to 32 binds per shader stage. - * We only use textures during the vertex and fragment stage, - * so 2 * 32 slots is a nice limit. */ - GPUTexture *bound_texs[DST_MAX_SLOTS]; - uint64_t bound_tex_slots; - uint64_t bound_tex_slots_persist; - - GPUUniformBuffer *bound_ubos[DST_MAX_SLOTS]; - uint64_t bound_ubo_slots; - uint64_t bound_ubo_slots_persist; - } RST; - struct { /* TODO(fclem) optimize: use chunks. */ DRWDebugLine *lines; DRWDebugSphere *spheres; } debug; - - struct { - char *buffer; - uint buffer_len; - uint buffer_ofs; - } uniform_names; } DRWManager; extern DRWManager DST; /* TODO: get rid of this and allow multi-threaded rendering. */ diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index aa401bcffa5..376bc69b392 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -170,13 +170,20 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool) /** \name Uniforms (DRW_shgroup_uniform) * \{ */ -static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, - int loc, - DRWUniformType type, - const void *value, - int length, - int arraysize) -{ +static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, + int loc, + DRWUniformType type, + const void *value, + eGPUSamplerState sampler_state, + int length, + int arraysize) +{ + if (loc == -1) { + /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */ + // BLI_assert(0); + return; + } + DRWUniformChunk *unichunk = shgroup->uniforms; /* Happens on first uniform or if chunk is full. */ if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) { @@ -202,22 +209,24 @@ static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup, BLI_assert(length <= 4); memcpy(uni->fvalue, value, sizeof(float) * length); break; + case DRW_UNIFORM_BLOCK: + uni->block = (GPUUniformBuffer *)value; + break; + case DRW_UNIFORM_BLOCK_REF: + uni->block_ref = (GPUUniformBuffer **)value; + break; + case DRW_UNIFORM_TEXTURE: + uni->texture = (GPUTexture *)value; + uni->sampler_state = sampler_state; + break; + case DRW_UNIFORM_TEXTURE_REF: + uni->texture_ref = (GPUTexture **)value; + uni->sampler_state = sampler_state; + break; default: uni->pvalue = (const float *)value; break; } - - return uni; -} - -static void drw_shgroup_builtin_uniform( - DRWShadingGroup *shgroup, int builtin, const void *value, int length, int arraysize) -{ - int loc = GPU_shader_get_builtin_uniform(shgroup->shader, builtin); - - if (loc != -1) { - drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_FLOAT, value, length, arraysize); - } } static void drw_shgroup_uniform(DRWShadingGroup *shgroup, @@ -227,61 +236,29 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup, int length, int arraysize) { - int location; - if (ELEM(type, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_PERSIST)) { - location = GPU_shader_get_uniform_block(shgroup->shader, name); - } - else { - location = GPU_shader_get_uniform(shgroup->shader, name); - } - - if (location == -1) { - /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */ - // BLI_assert(0); - return; - } - BLI_assert(arraysize > 0 && arraysize <= 16); BLI_assert(length >= 0 && length <= 16); - - DRWUniform *uni = drw_shgroup_uniform_create_ex( - shgroup, location, type, value, length, arraysize); - - /* If location is -2, the uniform has not yet been queried. - * We save the name for query just before drawing. */ - if (location == -2 || DRW_DEBUG_USE_UNIFORM_NAME) { - int ofs = DST.uniform_names.buffer_ofs; - int max_len = DST.uniform_names.buffer_len - ofs; - size_t len = strlen(name) + 1; - - if (len >= max_len) { - DST.uniform_names.buffer_len += MAX2(DST.uniform_names.buffer_len, len); - DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, - DST.uniform_names.buffer_len); - } - - char *dst = DST.uniform_names.buffer + ofs; - memcpy(dst, name, len); /* Copies NULL terminator. */ - - DST.uniform_names.buffer_ofs += len; - uni->name_ofs = ofs; - } + BLI_assert(!ELEM(type, + DRW_UNIFORM_BLOCK, + DRW_UNIFORM_BLOCK_REF, + DRW_UNIFORM_TEXTURE, + DRW_UNIFORM_TEXTURE_REF)); + int location = GPU_shader_get_uniform(shgroup->shader, name); + drw_shgroup_uniform_create_ex(shgroup, location, type, value, 0, length, arraysize); } void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex) { BLI_assert(tex != NULL); - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1); + int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE, tex, GPU_SAMPLER_MAX, 0, 1); } -/* Same as DRW_shgroup_uniform_texture but is guaranteed to be bound if shader does not change - * between shgrp. */ -void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup, - const char *name, - const GPUTexture *tex) +void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex) { BLI_assert(tex != NULL); - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_PERSIST, tex, 0, 1); + int loc = GPU_shader_get_texture_binding(shgroup->shader, name); + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, GPU_SAMPLER_MAX, 0, 1); } void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, @@ -289,22 +266,17 @@ void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const GPUUniformBuffer *ubo) { BLI_assert(ubo != NULL); - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1); + int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name); + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK, ubo, 0, 0, 1); } -/* Same as DRW_shgroup_uniform_block but is guaranteed to be bound if shader does not change - * between shgrp. */ -void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup, - const char *name, - const GPUUniformBuffer *ubo) +void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup, + const char *name, + GPUUniformBuffer **ubo) { BLI_assert(ubo != NULL); - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK_PERSIST, ubo, 0, 1); -} - -void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex) -{ - drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_REF, tex, 0, 1); + int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name); + drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK_REF, ubo, 0, 0, 1); } void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, @@ -441,7 +413,7 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, const float (*value)[4], int arraysize) { - int location = GPU_shader_get_uniform_ensure(shgroup->shader, name); + int location = GPU_shader_get_uniform(shgroup->shader, name); if (location == -1) { /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */ @@ -450,7 +422,8 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup, } for (int i = 0; i < arraysize; i++) { - drw_shgroup_uniform_create_ex(shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 4, 1); + drw_shgroup_uniform_create_ex( + shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 1); } } @@ -1196,52 +1169,49 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) shgroup->uniforms = NULL; /* TODO(fclem) make them builtin. */ - int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock"); - int model_ubo_location = GPU_shader_get_uniform_block(shader, "modelBlock"); - int info_ubo_location = GPU_shader_get_uniform_block(shader, "infoBlock"); + int view_ubo_location = GPU_shader_get_uniform_block_binding(shader, "viewBlock"); + int model_ubo_location = GPU_shader_get_uniform_block_binding(shader, "modelBlock"); + int info_ubo_location = GPU_shader_get_uniform_block_binding(shader, "infoBlock"); int baseinst_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_BASE_INSTANCE); int chunkid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_CHUNK); int resourceid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_ID); if (chunkid_location != -1) { drw_shgroup_uniform_create_ex( - shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 1); + shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 0, 1); } if (resourceid_location != -1) { drw_shgroup_uniform_create_ex( - shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 1); + shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 0, 1); } if (baseinst_location != -1) { drw_shgroup_uniform_create_ex( - shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 1); + shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 0, 1); } if (model_ubo_location != -1) { drw_shgroup_uniform_create_ex( - shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 1); + shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 0, 1); } else { + /* Note: This is only here to support old hardware fallback where uniform buffer is still + * too slow or buggy. */ int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL); int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV); - int modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP); if (model != -1) { - drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 1); + drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 0, 1); } if (modelinverse != -1) { drw_shgroup_uniform_create_ex( - shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 1); - } - if (modelviewprojection != -1) { - drw_shgroup_uniform_create_ex( - shgroup, modelviewprojection, DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX, NULL, 0, 1); + shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 0, 1); } } if (info_ubo_location != -1) { drw_shgroup_uniform_create_ex( - shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 1); + shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 0, 1); /* Abusing this loc to tell shgroup we need the obinfos. */ shgroup->objectinfo = 1; @@ -1252,25 +1222,21 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader) if (view_ubo_location != -1) { drw_shgroup_uniform_create_ex( - shgroup, view_ubo_location, DRW_UNIFORM_BLOCK_PERSIST, G_draw.view_ubo, 0, 1); - } - else { - /* Only here to support builtin shaders. This should not be used by engines. */ - /* TODO remove. */ - DRWViewUboStorage *storage = &DST.view_storage_cpy; - drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW, storage->viewmat, 16, 1); - drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW_INV, storage->viewinv, 16, 1); - drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION, storage->persmat, 16, 1); - drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION_INV, storage->persinv, 16, 1); - drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION, storage->winmat, 16, 1); - drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION_INV, storage->wininv, 16, 1); - drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_CLIPPLANES, storage->clipplanes, 4, 6); + shgroup, view_ubo_location, DRW_UNIFORM_BLOCK, G_draw.view_ubo, 0, 0, 1); } /* Not supported. */ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1); BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1); BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW_INV) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION_INV) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CLIPPLANES) == -1); + BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP) == -1); } static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass) @@ -1308,18 +1274,20 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass static void drw_shgroup_material_texture(DRWShadingGroup *grp, GPUMaterialTexture *tex, const char *name, + eGPUSamplerState state, int textarget) { GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget); - DRW_shgroup_uniform_texture(grp, name, gputex); + + int loc = GPU_shader_get_texture_binding(grp->shader, name); + drw_shgroup_uniform_create_ex(grp, loc, DRW_UNIFORM_TEXTURE, gputex, state, 0, 1); GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images); *gputex_ref = gputex; GPU_texture_ref(gputex); } -static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, - struct GPUMaterial *material) +void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material) { ListBase textures = GPU_material_textures(material); @@ -1328,11 +1296,14 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, if (tex->ima) { /* Image */ if (tex->tiled_mapping_name[0]) { - drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D_ARRAY); - drw_shgroup_material_texture(grp, tex, tex->tiled_mapping_name, GL_TEXTURE_1D_ARRAY); + drw_shgroup_material_texture( + grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D_ARRAY); + drw_shgroup_material_texture( + grp, tex, tex->tiled_mapping_name, tex->sampler_state, GL_TEXTURE_1D_ARRAY); } else { - drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D); + drw_shgroup_material_texture( + grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D); } } else if (tex->colorband) { @@ -1345,8 +1316,6 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, if (ubo != NULL) { DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo); } - - return grp; } GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[], @@ -1371,7 +1340,7 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa if (shgroup) { drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass)); - drw_shgroup_material_inputs(shgroup, material); + DRW_shgroup_add_material_resources(shgroup, material); } return shgroup; } @@ -1390,7 +1359,7 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader, BLI_assert(tf_target != NULL); DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass); drw_shgroup_init(shgroup, shader); - drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 1); + drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 0, 1); return shgroup; } @@ -1922,9 +1891,28 @@ DRWPass *DRW_pass_create(const char *name, DRWState state) pass->handle = DST.pass_handle; DRW_handle_increment(&DST.pass_handle); + pass->original = NULL; + pass->next = NULL; + + return pass; +} + +DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state) +{ + DRWPass *pass = DRW_pass_create(name, state); + pass->original = original; + return pass; } +/* Link two passes so that they are both rendered if the first one is being drawn. */ +void DRW_pass_link(DRWPass *first, DRWPass *second) +{ + BLI_assert(first != second); + BLI_assert(first->next == NULL); + first->next = second; +} + bool DRW_pass_is_empty(DRWPass *pass) { LISTBASE_FOREACH (DRWShadingGroup *, shgroup, &pass->shgroups) { diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 6c62d4d2405..144ce573460 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -22,6 +22,7 @@ #include "draw_manager.h" +#include "BLI_alloca.h" #include "BLI_math.h" #include "BLI_math_bits.h" #include "BLI_memblock.h" @@ -65,7 +66,6 @@ typedef struct DRWCommandsState { /* Legacy matrix support. */ int obmat_loc; int obinv_loc; - int mvp_loc; /* Selection ID state. */ GPUVertBuf *select_buf; uint select_id; @@ -655,8 +655,7 @@ static void draw_compute_culling(DRWView *view) BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup, DRWResourceHandle *handle, float obmat_loc, - float obinv_loc, - float mvp_loc) + float obinv_loc) { /* Still supported for compatibility with gpu_shader_* but should be forbidden. */ DRWObjectMatrix *ob_mats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, handle); @@ -666,13 +665,6 @@ BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup, if (obinv_loc != -1) { GPU_shader_uniform_vector(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse); } - /* Still supported for compatibility with gpu_shader_* but should be forbidden - * and is slow (since it does not cache the result). */ - if (mvp_loc != -1) { - float mvp[4][4]; - mul_m4_m4m4(mvp, DST.view_active->storage.persmat, ob_mats->model); - GPU_shader_uniform_vector(shgroup->shader, mvp_loc, 16, 1, (float *)mvp); - } } BLI_INLINE void draw_geometry_bind(DRWShadingGroup *shgroup, GPUBatch *geom) @@ -744,107 +736,6 @@ BLI_INLINE void draw_indirect_call(DRWShadingGroup *shgroup, DRWCommandsState *s } } -enum { - BIND_NONE = 0, - BIND_TEMP = 1, /* Release slot after this shading group. */ - BIND_PERSIST = 2, /* Release slot only after the next shader change. */ -}; - -static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type) -{ - uint64_t slot = 1llu << (unsigned long)slot_idx; - *slots |= slot; - if (bind_type == BIND_PERSIST) { - *persist_slots |= slot; - } -} - -static int get_empty_slot_index(uint64_t slots) -{ - uint64_t empty_slots = ~slots; - /* Find first empty slot using bitscan. */ - if (empty_slots != 0) { - if ((empty_slots & 0xFFFFFFFFlu) != 0) { - return (int)bitscan_forward_uint(empty_slots); - } - else { - return (int)bitscan_forward_uint(empty_slots >> 32) + 32; - } - } - else { - /* Greater than GPU_max_textures() */ - return 99999; - } -} - -static void bind_texture(GPUTexture *tex, char bind_type) -{ - int idx = GPU_texture_bound_number(tex); - if (idx == -1) { - /* Texture isn't bound yet. Find an empty slot and bind it. */ - idx = get_empty_slot_index(DST.RST.bound_tex_slots); - - if (idx < GPU_max_textures()) { - GPUTexture **gpu_tex_slot = &DST.RST.bound_texs[idx]; - /* Unbind any previous texture. */ - if (*gpu_tex_slot != NULL) { - GPU_texture_unbind(*gpu_tex_slot); - } - GPU_texture_bind(tex, idx); - *gpu_tex_slot = tex; - } - else { - printf("Not enough texture slots! Reduce number of textures used by your shader.\n"); - return; - } - } - else { - /* This texture slot was released but the tex - * is still bound. Just flag the slot again. */ - BLI_assert(DST.RST.bound_texs[idx] == tex); - } - set_bound_flags(&DST.RST.bound_tex_slots, &DST.RST.bound_tex_slots_persist, idx, bind_type); -} - -static void bind_ubo(GPUUniformBuffer *ubo, char bind_type) -{ - int idx = GPU_uniformbuffer_bindpoint(ubo); - if (idx == -1) { - /* UBO isn't bound yet. Find an empty slot and bind it. */ - idx = get_empty_slot_index(DST.RST.bound_ubo_slots); - - /* [0..1] are reserved ubo slots. */ - idx += 2; - - if (idx < GPU_max_ubo_binds()) { - GPUUniformBuffer **gpu_ubo_slot = &DST.RST.bound_ubos[idx]; - /* Unbind any previous UBO. */ - if (*gpu_ubo_slot != NULL) { - GPU_uniformbuffer_unbind(*gpu_ubo_slot); - } - GPU_uniformbuffer_bind(ubo, idx); - *gpu_ubo_slot = ubo; - } - else { - /* printf so user can report bad behavior */ - printf("Not enough ubo slots! This should not happen!\n"); - /* This is not depending on user input. - * It is our responsibility to make sure there is enough slots. */ - BLI_assert(0); - return; - } - } - else { - BLI_assert(idx < 64); - /* This UBO slot was released but the UBO is - * still bound here. Just flag the slot again. */ - BLI_assert(DST.RST.bound_ubos[idx] == ubo); - } - /* Remove offset for flag bitfield. */ - idx -= 2; - set_bound_flags(&DST.RST.bound_ubo_slots, &DST.RST.bound_ubo_slots_persist, idx, bind_type); -} - #ifndef NDEBUG /** * Opengl specification is strict on buffer binding. @@ -900,28 +791,6 @@ static bool ubo_bindings_validate(DRWShadingGroup *shgroup) } #endif -static void release_texture_slots(bool with_persist) -{ - if (with_persist) { - DST.RST.bound_tex_slots = 0; - DST.RST.bound_tex_slots_persist = 0; - } - else { - DST.RST.bound_tex_slots &= DST.RST.bound_tex_slots_persist; - } -} - -static void release_ubo_slots(bool with_persist) -{ - if (with_persist) { - DST.RST.bound_ubo_slots = 0; - DST.RST.bound_ubo_slots_persist = 0; - } - else { - DST.RST.bound_ubo_slots &= DST.RST.bound_ubo_slots_persist; - } -} - static void draw_update_uniforms(DRWShadingGroup *shgroup, DRWCommandsState *state, bool *use_tfeedback) @@ -929,69 +798,42 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) { DRWUniform *uni = unichunk->uniforms; for (int i = 0; i < unichunk->uniform_used; i++, uni++) { - GPUTexture *tex; - GPUUniformBuffer *ubo; - if (uni->location == -2) { - uni->location = GPU_shader_get_uniform_ensure(shgroup->shader, - DST.uniform_names.buffer + uni->name_ofs); - if (uni->location == -1) { - continue; - } - } - const void *data = uni->pvalue; - if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) { - data = uni->fvalue; - } switch (uni->type) { case DRW_UNIFORM_INT_COPY: + GPU_shader_uniform_vector_int( + shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue); + break; case DRW_UNIFORM_INT: GPU_shader_uniform_vector_int( - shgroup->shader, uni->location, uni->length, uni->arraysize, data); + shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue); break; case DRW_UNIFORM_FLOAT_COPY: + GPU_shader_uniform_vector( + shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue); + break; case DRW_UNIFORM_FLOAT: GPU_shader_uniform_vector( - shgroup->shader, uni->location, uni->length, uni->arraysize, data); + shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue); break; case DRW_UNIFORM_TEXTURE: - tex = (GPUTexture *)uni->pvalue; - BLI_assert(tex); - bind_texture(tex, BIND_TEMP); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); - break; - case DRW_UNIFORM_TEXTURE_PERSIST: - tex = (GPUTexture *)uni->pvalue; - BLI_assert(tex); - bind_texture(tex, BIND_PERSIST); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + GPU_texture_bind_ex(uni->texture, uni->sampler_state, uni->location, false); break; case DRW_UNIFORM_TEXTURE_REF: - tex = *((GPUTexture **)uni->pvalue); - BLI_assert(tex); - bind_texture(tex, BIND_TEMP); - GPU_shader_uniform_texture(shgroup->shader, uni->location, tex); + GPU_texture_bind_ex(*uni->texture_ref, uni->sampler_state, uni->location, false); break; case DRW_UNIFORM_BLOCK: - ubo = (GPUUniformBuffer *)uni->pvalue; - bind_ubo(ubo, BIND_TEMP); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + GPU_uniformbuffer_bind(uni->block, uni->location); break; - case DRW_UNIFORM_BLOCK_PERSIST: - ubo = (GPUUniformBuffer *)uni->pvalue; - bind_ubo(ubo, BIND_PERSIST); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + case DRW_UNIFORM_BLOCK_REF: + GPU_uniformbuffer_bind(*uni->block_ref, uni->location); break; case DRW_UNIFORM_BLOCK_OBMATS: state->obmats_loc = uni->location; - ubo = DST.vmempool->matrices_ubo[0]; - GPU_uniformbuffer_bind(ubo, 0); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[0], uni->location); break; case DRW_UNIFORM_BLOCK_OBINFOS: state->obinfos_loc = uni->location; - ubo = DST.vmempool->obinfos_ubo[0]; - GPU_uniformbuffer_bind(ubo, 1); - GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo); + GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[0], uni->location); break; case DRW_UNIFORM_RESOURCE_CHUNK: state->chunkid_loc = uni->location; @@ -1001,9 +843,9 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, state->resourceid_loc = uni->location; break; case DRW_UNIFORM_TFEEDBACK_TARGET: - BLI_assert(data && (*use_tfeedback == false)); - *use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader, - ((GPUVertBuf *)data)->vbo_id); + BLI_assert(uni->pvalue && (*use_tfeedback == false)); + *use_tfeedback = GPU_shader_transform_feedback_enable( + shgroup->shader, ((GPUVertBuf *)uni->pvalue)->vbo_id); break; /* Legacy/Fallback support. */ case DRW_UNIFORM_BASE_INSTANCE: @@ -1015,9 +857,6 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup, case DRW_UNIFORM_MODEL_MATRIX_INVERSE: state->obinv_loc = uni->location; break; - case DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX: - state->mvp_loc = uni->location; - break; } } } @@ -1110,7 +949,7 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa } if (state->obmats_loc != -1) { GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]); - GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], 0); + GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], state->obmats_loc); } if (state->obinfos_loc != -1) { GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]); @@ -1153,10 +992,8 @@ static void draw_call_single_do(DRWShadingGroup *shgroup, draw_call_resource_bind(state, &handle); /* TODO This is Legacy. Need to be removed. */ - if (state->obmats_loc == -1 && - (state->obmat_loc != -1 || state->obinv_loc != -1 || state->mvp_loc != -1)) { - draw_legacy_matrix_update( - shgroup, &handle, state->obmat_loc, state->obinv_loc, state->mvp_loc); + if (state->obmats_loc == -1 && (state->obmat_loc != -1 || state->obinv_loc != -1)) { + draw_legacy_matrix_update(shgroup, &handle, state->obmat_loc, state->obinv_loc); } if (G.f & G_FLAG_PICKSEL) { @@ -1262,7 +1099,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) .resourceid_loc = -1, .obmat_loc = -1, .obinv_loc = -1, - .mvp_loc = -1, .drw_state_enabled = 0, .drw_state_disabled = 0, }; @@ -1273,6 +1109,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) if (shader_changed) { if (DST.shader) { GPU_shader_unbind(); + + /* Unbinding can be costly. Skip in normal condition. */ + if (G.debug & G_DEBUG_GPU) { + GPU_texture_unbind_all(); + } } GPU_shader_bind(shgroup->shader); DST.shader = shgroup->shader; @@ -1283,9 +1124,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state) DST.batch = NULL; } - release_ubo_slots(shader_changed); - release_texture_slots(shader_changed); - draw_update_uniforms(shgroup, &state, &use_tfeedback); drw_state_set(pass_state); @@ -1426,6 +1264,11 @@ static void drw_draw_pass_ex(DRWPass *pass, DRWShadingGroup *start_group, DRWShadingGroup *end_group) { + if (pass->original) { + start_group = pass->original->shgroups.first; + end_group = pass->original->shgroups.last; + } + if (start_group == NULL) { return; } @@ -1462,24 +1305,9 @@ static void drw_draw_pass_ex(DRWPass *pass, } } - /* Clear Bound textures */ - for (int i = 0; i < DST_MAX_SLOTS; i++) { - if (DST.RST.bound_texs[i] != NULL) { - GPU_texture_unbind(DST.RST.bound_texs[i]); - DST.RST.bound_texs[i] = NULL; - } - } - - /* Clear Bound Ubos */ - for (int i = 0; i < DST_MAX_SLOTS; i++) { - if (DST.RST.bound_ubos[i] != NULL) { - GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]); - DST.RST.bound_ubos[i] = NULL; - } - } - if (DST.shader) { GPU_shader_unbind(); + GPU_texture_unbind_all(); DST.shader = NULL; } @@ -1511,7 +1339,9 @@ static void drw_draw_pass_ex(DRWPass *pass, void DRW_draw_pass(DRWPass *pass) { - drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last); + for (; pass; pass = pass->next) { + drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last); + } } /* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */ diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index 0d6527421d0..6304b707cb9 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -343,27 +343,12 @@ GPUShader *DRW_shader_create_with_transform_feedback(const char *vert, __func__); } -GPUShader *DRW_shader_create_2d(const char *frag, const char *defines) -{ - return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, __func__); -} - -GPUShader *DRW_shader_create_3d(const char *frag, const char *defines) -{ - return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, __func__); -} - GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines) { return GPU_shader_create( datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, __func__); } -GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig sh_cfg) -{ - return GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); -} - GPUMaterial *DRW_shader_find_from_world(World *wo, const void *engine_type, const int options, @@ -398,6 +383,7 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma, GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, World *wo, + struct bNodeTree *ntree, const void *engine_type, const int options, const bool is_volume_shader, @@ -408,7 +394,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, bool deferred) { GPUMaterial *mat = NULL; - if (DRW_state_is_image_render()) { + if (DRW_state_is_image_render() || !deferred) { mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options); } @@ -416,7 +402,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id); mat = GPU_material_from_nodetree(scene, NULL, - wo->nodetree, + ntree, &wo->gpumaterial, engine_type, options, @@ -437,6 +423,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene, GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, Material *ma, + struct bNodeTree *ntree, const void *engine_type, const int options, const bool is_volume_shader, @@ -447,7 +434,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, bool deferred) { GPUMaterial *mat = NULL; - if (DRW_state_is_image_render()) { + if (DRW_state_is_image_render() || !deferred) { mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options); } @@ -455,7 +442,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene, scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id); mat = GPU_material_from_nodetree(scene, ma, - ma->nodetree, + ntree, &ma->gpumaterial, engine_type, options, diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c index 6abab38e1e6..0cb6535b1c1 100644 --- a/source/blender/draw/intern/draw_manager_texture.c +++ b/source/blender/draw/intern/draw_manager_texture.c @@ -61,17 +61,17 @@ static bool drw_texture_format_supports_framebuffer(eGPUTextureFormat format) void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags) { - GPU_texture_bind(tex, 0); if (flags & DRW_TEX_MIPMAP) { GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER); + GPU_texture_bind(tex, 0); GPU_texture_generate_mipmap(tex); + GPU_texture_unbind(tex); } else { GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER); } GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP, true); GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE); - GPU_texture_unbind(tex); } GPUTexture *DRW_texture_create_1d(int w, diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 4203c2677b7..a2a1f7eb1d2 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -62,67 +62,6 @@ /* *************************************************** */ /* CURRENT FRAME DRAWING */ -/* Draw current frame number in a little green box beside the current frame indicator */ -void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag) -{ - Scene *scene = CTX_data_scene(C); - const float time = scene->r.cfra + scene->r.subframe; - const float cfra = (float)(time * scene->r.framelen); - const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0; - - const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; - uchar col[4]; - float color[4]; - float xscale, x, y; - char numstr[32] = " t "; /* t is the character to start replacing from */ - float hlen; - int slen; - - /* because the frame number text is subject to the same scaling as the contents of the view */ - UI_view2d_scale_get(v2d, &xscale, NULL); - GPU_matrix_push(); - GPU_matrix_scale_2f(1.0f / xscale, 1.0f); - - /* get timecode string - * - padding on str-buf passed so that it doesn't sit on the frame indicator - */ - if (show_time) { - BLI_timecode_string_from_time( - &numstr[2], sizeof(numstr) - 2, 0, FRA2TIME(cfra), FPS, U.timecode_style); - } - else { - BLI_timecode_string_from_time_seconds(&numstr[2], sizeof(numstr) - 2, 1, cfra); - } - - slen = UI_fontstyle_string_width(fstyle, numstr) - 1; - hlen = slen * 0.5f; - - /* get starting coordinates for drawing */ - x = cfra * xscale; - y = -0.1f * U.widget_unit; - - /* draw green box around/behind text */ - UI_GetThemeColor4fv(TH_CFRAME, color); - color[3] = 3.0f; - - UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - x - hlen - 0.1f * U.widget_unit, - y + 3.0f, - x + hlen + 0.1f * U.widget_unit, - y - 3.0f + U.widget_unit, - 0.1f * U.widget_unit, - color); - - /* draw current frame number */ - UI_GetThemeColor4ubv(TH_TEXT_HI, col); - UI_fontstyle_draw_simple( - fstyle, x - hlen - 0.15f * U.widget_unit, y + 0.28f * U.widget_unit, numstr, col); - - /* restore view transform */ - GPU_matrix_pop(); -} - /* General call for drawing current frame indicator in animation editor */ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag) { diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 04061ceea51..0e9b870df88 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -1827,7 +1827,7 @@ static int insert_key_exec(bContext *C, wmOperator *op) * updated since the last switching to the edit mode will be keyframed correctly */ if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) { - ED_object_mode_toggle(C, OB_MODE_EDIT); + ED_object_mode_set(C, OB_MODE_OBJECT); ob_edit_mode = true; } @@ -1843,7 +1843,7 @@ static int insert_key_exec(bContext *C, wmOperator *op) /* restore the edit mode if necessary */ if (ob_edit_mode) { - ED_object_mode_toggle(C, OB_MODE_EDIT); + ED_object_mode_set(C, OB_MODE_EDIT); } /* report failure or do updates? */ diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index af591e0c7c5..ef9bb7e0c88 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -359,7 +359,7 @@ static void font_undosys_step_decode( struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) { /* TODO(campbell): undo_system: use low-level API to set mode. */ - ED_object_mode_set(C, OB_MODE_EDIT); + ED_object_mode_set_ex(C, OB_MODE_EDIT, false, NULL); BLI_assert(font_undosys_poll(C)); FontUndoStep *us = (FontUndoStep *)us_p; diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c index 1fdf1160d09..a3921791427 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c @@ -67,7 +67,6 @@ typedef struct SnapGizmo3D { /* We could have other snap contexts, for now only support 3D view. */ SnapObjectContext *snap_context_v3d; int mval[2]; - short snap_elem; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmKeyMap *keymap; @@ -75,6 +74,7 @@ typedef struct SnapGizmo3D { bool invert_snap; #endif int use_snap_override; + short snap_elem; } SnapGizmo3D; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK @@ -82,11 +82,8 @@ static bool invert_snap(const wmGizmo *gz, const wmWindowManager *wm, const wmEv { SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; wmKeyMap *keymap = WM_keymap_active(wm, gizmo_snap->keymap); - if (!keymap) { - return false; - } - int snap_on = gizmo_snap->snap_on; + const int snap_on = gizmo_snap->snap_on; for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { if (kmi->flag & KMI_INACTIVE) { continue; @@ -408,14 +405,21 @@ static void gizmo_snap_draw(const bContext *C, wmGizmo *gz) static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2]) { SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz; + #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK wmWindowManager *wm = CTX_wm_manager(C); - const bool invert = invert_snap(gz, wm, wm->winactive->eventstate); + if (gizmo_snap->keymap == NULL) { + gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); + RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on); + } + + const bool invert = wm->winactive ? invert_snap(gz, wm, wm->winactive->eventstate) : false; if (gizmo_snap->invert_snap == invert && gizmo_snap->mval[0] == mval[0] && gizmo_snap->mval[1] == mval[1]) { /* Performance, do not update. */ return gizmo_snap->snap_elem ? 0 : -1; } + gizmo_snap->invert_snap = invert; #else if (gizmo_snap->mval[0] == mval[0] && gizmo_snap->mval[1] == mval[1]) { @@ -425,14 +429,6 @@ static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2]) #endif copy_v2_v2_int(gizmo_snap->mval, mval); -#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK - if (gizmo_snap->keymap == NULL) { - gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); - gizmo_snap->snap_on = -1; - RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on); - } -#endif - ARegion *region = CTX_wm_region(C); View3D *v3d = CTX_wm_view3d(C); const float mval_fl[2] = {UNPACK2(mval)}; diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index c53b90fbfee..723c7d214e3 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -1729,17 +1729,16 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) } /* Turn brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable) +static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable) { if (p->erasercursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor); + WM_paint_cursor_end(p->erasercursor); p->erasercursor = NULL; } else if (enable && !p->erasercursor) { /* enable cursor */ - p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, + p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, /* XXX */ gpencil_draw_eraser, @@ -1794,17 +1793,17 @@ static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) } /* Turn *stabilizer* brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_stabilizer_cursor(bContext *C, tGPsdata *p, short enable) +static void gpencil_draw_toggle_stabilizer_cursor(tGPsdata *p, short enable) { if (p->stabilizer_cursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), p->stabilizer_cursor); + WM_paint_cursor_end(p->stabilizer_cursor); p->stabilizer_cursor = NULL; } else if (enable && !p->stabilizer_cursor) { /* enable cursor */ p->stabilizer_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p); + SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p); } } @@ -1828,10 +1827,10 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* check size of buffer before cleanup, to determine if anything happened here */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* turn off radial brush cursor */ - gpencil_draw_toggle_eraser_cursor(C, p, false); + gpencil_draw_toggle_eraser_cursor(p, false); } else if (p->paintmode == GP_PAINTMODE_DRAW) { - gpencil_draw_toggle_stabilizer_cursor(C, p, false); + gpencil_draw_toggle_stabilizer_cursor(p, false); } /* always store the new eraser size to be used again next time @@ -2039,7 +2038,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph /* handle draw event */ static void annotation_draw_apply_event( - bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) + wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) { tGPsdata *p = op->customdata; PointerRNA itemptr; @@ -2056,14 +2055,14 @@ static void annotation_draw_apply_event( /* Using permanent stabilization, shift will deactivate the flag. */ if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) { if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { - gpencil_draw_toggle_stabilizer_cursor(C, p, false); + gpencil_draw_toggle_stabilizer_cursor(p, false); p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; } } /* Not using any stabilization flag. Activate temporal one. */ else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); } } /* verify key status for straight lines */ @@ -2092,7 +2091,7 @@ static void annotation_draw_apply_event( so activate the temp flag back again. */ if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; } } @@ -2102,7 +2101,7 @@ static void annotation_draw_apply_event( else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { /* Reset temporal stabilizer flag and remove cursor. */ p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, false); + gpencil_draw_toggle_stabilizer_cursor(p, false); } } @@ -2296,7 +2295,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { - gpencil_draw_toggle_eraser_cursor(C, p, true); + gpencil_draw_toggle_eraser_cursor(p, true); } else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) { @@ -2313,11 +2312,11 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius"); if (RNA_boolean_get(op->ptr, "use_stabilizer")) { p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); } else if (event->shift > 0) { p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; - gpencil_draw_toggle_stabilizer_cursor(C, p, true); + gpencil_draw_toggle_stabilizer_cursor(p, true); } } /* set cursor @@ -2333,7 +2332,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ - annotation_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); op->flag |= OP_IS_MODAL_CURSOR_REGION; } else { @@ -2425,7 +2424,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, 0.5f); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); } else if (dist >= factor) { int slices = 2 + (int)((dist - 1.0) / factor); @@ -2434,7 +2433,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, n * i); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); } } } @@ -2562,7 +2561,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) * Just hiding this makes it seem like * you can paint again... */ - gpencil_draw_toggle_eraser_cursor(C, p, false); + gpencil_draw_toggle_eraser_cursor(p, false); } } @@ -2647,7 +2646,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) p->paintmode = RNA_enum_get(op->ptr, "mode"); } - gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); + gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER); /* not painting, so start stroke (this should be mouse-button down) */ p = gpencil_stroke_begin(C, op); @@ -2681,8 +2680,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* TODO(sergey): Possibly evaluating dependency graph from modal operator? */ - annotation_draw_apply_event( - C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); /* finish painting operation if anything went wrong just now */ if (p->status == GP_STATUS_ERROR) { diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 4330a07057e..8771fcb0c8d 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -370,7 +370,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op) if (mode == OB_MODE_PAINT_GPENCIL) { /* Be sure we have brushes and Paint settings. - * Need Draw and Vertex (used fro Tint). */ + * Need Draw and Vertex (used for Tint). */ BKE_paint_ensure(ts, (Paint **)&ts->gp_paint); BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint); @@ -485,11 +485,13 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op) } if (mode == OB_MODE_SCULPT_GPENCIL) { - /* be sure we have brushes */ + /* Be sure we have brushes. */ BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint); - BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint); - BKE_brush_gpencil_sculpt_presets(bmain, ts, false); + const bool reset_mode = (ts->gp_sculptpaint->paint.brush == NULL); + BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode); + + BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint); } /* setup other modes */ @@ -592,11 +594,13 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op) } if (mode == OB_MODE_WEIGHT_GPENCIL) { - /* be sure we have brushes */ + /* Be sure we have brushes. */ BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint); - BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint); - BKE_brush_gpencil_weight_presets(bmain, ts, false); + const bool reset_mode = (ts->gp_weightpaint->paint.brush == NULL); + BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode); + + BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint); } /* setup other modes */ @@ -696,11 +700,13 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op) } if (mode == OB_MODE_VERTEX_GPENCIL) { - /* be sure we have brushes */ + /* Be sure we have brushes. */ BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint); - BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint); - BKE_brush_gpencil_vertex_presets(bmain, ts, false); + const bool reset_mode = (ts->gp_vertexpaint->paint.brush == NULL); + BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode); + + BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint); /* Ensure Palette by default. */ BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C)); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 4e83c4fb11c..06079c34d12 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -2299,18 +2299,17 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr) } /* Turn brush cursor in 3D view on/off */ -static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable) +static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable) { if (p->erasercursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor); + WM_paint_cursor_end(p->erasercursor); p->erasercursor = NULL; } else if (enable && !p->erasercursor) { ED_gpencil_toggle_brush_cursor(p->C, false, NULL); /* enable cursor */ - p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, + p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, /* XXX */ gpencil_draw_eraser, @@ -2335,7 +2334,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* check size of buffer before cleanup, to determine if anything happened here */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* turn off radial brush cursor */ - gpencil_draw_toggle_eraser_cursor(C, p, false); + gpencil_draw_toggle_eraser_cursor(p, false); } /* always store the new eraser size to be used again next time @@ -3154,7 +3153,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* TODO: set any additional settings that we can take from the events? * if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { - gpencil_draw_toggle_eraser_cursor(C, p, true); + gpencil_draw_toggle_eraser_cursor(p, true); } else { ED_gpencil_toggle_brush_cursor(C, true, NULL); @@ -3700,7 +3699,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) p->paintmode = RNA_enum_get(op->ptr, "mode"); } - gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER); + gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER); /* not painting, so start stroke (this should be mouse-button down) */ p = gpencil_stroke_begin(C, op); diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 69d22b52ded..7accf48832a 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -43,6 +43,7 @@ #include "BKE_context.h" #include "BKE_gpencil.h" +#include "BKE_material.h" #include "BKE_report.h" #include "UI_interface.h" @@ -67,6 +68,45 @@ /** \name Shared Utilities * \{ */ +/* Check if mouse inside stroke. */ +static bool gpencil_point_inside_stroke(bGPDstroke *gps, + GP_SpaceConversion *gsc, + int mouse[2], + const float diff_mat[4][4]) +{ + bool hit = false; + if (gps->totpoints == 0) { + return hit; + } + + int(*mcoords)[2] = NULL; + int len = gps->totpoints; + mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__); + + /* Convert stroke to 2D array of points. */ + bGPDspoint *pt; + int i; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + bGPDspoint pt2; + gp_point_to_parent_space(pt, diff_mat, &pt2); + gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]); + } + + /* Compute boundbox of lasso (for faster testing later). */ + rcti rect; + BLI_lasso_boundbox(&rect, mcoords, len); + + /* Test if point inside stroke. */ + hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) && + BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) && + BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX)); + + /* Free memory. */ + MEM_SAFE_FREE(mcoords); + + return hit; +} + /* Convert sculpt mask mode to Select mode */ static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode) { @@ -1118,10 +1158,8 @@ typedef bool (*GPencilTestFn)(bGPDstroke *gps, const float diff_mat[4][4], void *user_data); -static int gpencil_generic_select_exec(bContext *C, - wmOperator *op, - GPencilTestFn is_inside_fn, - void *user_data) +static int gpencil_generic_select_exec( + bContext *C, wmOperator *op, GPencilTestFn is_inside_fn, rcti box, void *user_data) { Object *ob = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -1143,7 +1181,6 @@ static int gpencil_generic_select_exec(bContext *C, ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)); const bool segmentmode = ((selectmode == GP_SELECTMODE_SEGMENT) && ((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0)); - const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const float scale = ts->gp_sculpt.isect_threshold; @@ -1180,15 +1217,13 @@ static int gpencil_generic_select_exec(bContext *C, /* select/deselect points */ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; + bool whole = false; bGPDspoint *pt; int i; bool hit = false; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if (pt->runtime.pt_orig == NULL) { - continue; - } - bGPDspoint *pt_active = pt->runtime.pt_orig; + bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; /* convert point coords to screenspace */ const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data); @@ -1198,9 +1233,10 @@ static int gpencil_generic_select_exec(bContext *C, if (sel_op_result != -1) { SET_FLAG_FROM_TEST(pt_active->flag, sel_op_result, GP_SPOINT_SELECT); changed = true; + hit = true; - /* expand selection to segment */ - if ((sel_op_result != -1) && (segmentmode)) { + /* Expand selection to segment. */ + if (segmentmode) { bool hit_select = (bool)(pt_active->flag & GP_SPOINT_SELECT); float r_hita[3], r_hitb[3]; ED_gpencil_select_stroke_segment( @@ -1216,16 +1252,28 @@ static int gpencil_generic_select_exec(bContext *C, } } - /* if stroke mode expand selection */ - if (strokemode) { - const bool is_select = BKE_gpencil_stroke_select_check(gps_active); - const bool is_inside = hit; + /* If nothing hit, check if the mouse is inside a filled stroke using the center or + * Box or lasso area. */ + if (!hit) { + /* Only check filled strokes. */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { + continue; + } + int mval[2]; + mval[0] = (box.xmax + box.xmin) / 2; + mval[1] = (box.ymax + box.ymin) / 2; + + whole = gpencil_point_inside_stroke(gps_active, &gsc, mval, gpstroke_iter.diff_mat); + } + + /* if stroke mode expand selection. */ + if ((strokemode) || (whole)) { + const bool is_select = BKE_gpencil_stroke_select_check(gps_active) || whole; + const bool is_inside = hit || whole; const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) { - continue; - } bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt; if (sel_op_result) { @@ -1261,7 +1309,6 @@ static int gpencil_generic_select_exec(bContext *C, WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL); } - return OPERATOR_FINISHED; } @@ -1293,7 +1340,8 @@ static int gpencil_box_select_exec(bContext *C, wmOperator *op) { struct GP_SelectBoxUserData data = {0}; WM_operator_properties_border_to_rcti(op, &data.rect); - return gpencil_generic_select_exec(C, op, gpencil_test_box, &data); + rcti rect = data.rect; + return gpencil_generic_select_exec(C, op, gpencil_test_box, rect, &data); } void GPENCIL_OT_select_box(wmOperatorType *ot) @@ -1360,7 +1408,8 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) /* Compute boundbox of lasso (for faster testing later). */ BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len); - int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data); + rcti rect = data.rect; + int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, rect, &data); MEM_freeN((void *)data.mcoords); @@ -1424,7 +1473,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); /* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */ - const float radius = 0.50f * U.widget_unit; + const float radius = 0.4f * U.widget_unit; const int radius_squared = (int)(radius * radius); const bool use_shift_extend = RNA_boolean_get(op->ptr, "use_shift_extend"); @@ -1469,12 +1518,19 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) RNA_int_get_array(op->ptr, "location", mval); /* First Pass: Find stroke point which gets hit */ - /* XXX: maybe we should go from the top of the stack down instead... */ GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; bGPDspoint *pt; int i; + /* Check boundbox to speedup. */ + float fmval[2]; + copy_v2fl_v2i(fmval, mval); + if (!ED_gpencil_stroke_check_collision( + &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) { + continue; + } + /* firstly, check for hit-point */ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { int xy[2]; @@ -1502,11 +1558,27 @@ static int gpencil_select_exec(bContext *C, wmOperator *op) } } } + if (ELEM(NULL, hit_stroke, hit_point)) { + /* If nothing hit, check if the mouse is inside any filled stroke. + * Only check filling materials. */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) { + continue; + } + bool hit_fill = gpencil_point_inside_stroke(gps, &gsc, mval, gpstroke_iter.diff_mat); + if (hit_fill) { + hit_stroke = gps_active; + hit_point = &gps_active->points[0]; + /* Extend selection to all stroke. */ + whole = true; + } + } } GP_EVALUATED_STROKES_END(gpstroke_iter); /* Abort if nothing hit... */ if (ELEM(NULL, hit_stroke, hit_point)) { + if (deselect_all) { /* since left mouse select change, deselect all if click outside any hit */ deselect_all_selected(C); diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 3cab26eab44..1962eba5017 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -1871,19 +1871,18 @@ void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata) if (gset->paintcursor && !enable) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); + WM_paint_cursor_end(gset->paintcursor); gset->paintcursor = NULL; } else if (enable) { /* in some situations cursor could be duplicated, so it is better disable first if exist */ if (gset->paintcursor) { /* clear cursor */ - WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor); + WM_paint_cursor_end(gset->paintcursor); gset->paintcursor = NULL; } /* enable cursor */ - gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, + gset->paintcursor = WM_paint_cursor_activate(SPACE_TYPE_ANY, RGN_TYPE_ANY, gp_brush_cursor_poll, gp_brush_cursor_draw, diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 7d38792f332..426a470b128 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -652,9 +652,6 @@ enum eAnimEditDraw_CurrentFrame { /* main call to draw current-frame indicator in an Animation Editor */ void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag); -/* main call to draw "number box" in scrollbar for current frame indicator */ -void ANIM_draw_cfra_number(const struct bContext *C, struct View2D *v2d, short flag); - /* ------------- Preview Range Drawing -------------- */ /* main call to draw preview range curtains */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 5adc99a8ae0..a2a8fbab6b3 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -212,13 +212,11 @@ bool ED_object_editmode_load(struct Main *bmain, struct Object *obedit); void ED_object_vpaintmode_enter_ex(struct Main *bmain, struct Depsgraph *depsgraph, - struct wmWindowManager *wm, struct Scene *scene, struct Object *ob); void ED_object_vpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph); void ED_object_wpaintmode_enter_ex(struct Main *bmain, struct Depsgraph *depsgraph, - struct wmWindowManager *wm, struct Scene *scene, struct Object *ob); void ED_object_wpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph); @@ -329,11 +327,12 @@ bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, eObjectMode mode, struct ReportList *reports); -void ED_object_mode_toggle(struct bContext *C, eObjectMode mode); -void ED_object_mode_set(struct bContext *C, eObjectMode mode); -void ED_object_mode_exit(struct bContext *C, struct Depsgraph *depsgraph); +bool ED_object_mode_set_ex(struct bContext *C, + eObjectMode mode, + bool use_undo, + struct ReportList *reports); +bool ED_object_mode_set(struct bContext *C, eObjectMode mode); -bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode); void ED_object_mode_generic_exit(struct Main *bmain, struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index 9969acd04b7..a62deb9d69f 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -162,6 +162,19 @@ int BIF_countTransformOrientation(const struct bContext *C); void Transform_Properties(struct wmOperatorType *ot, int flags); +/* *** transform_orientations.c *** */ +void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]); +short ED_transform_calc_orientation_from_type_ex(const struct bContext *C, + float r_mat[3][3], + /* extra args */ + struct Scene *scene, + struct RegionView3D *rv3d, + struct Object *ob, + struct Object *obedit, + const short orientation_type, + int orientation_index_custom, + const int pivot_point); + /* transform gizmos */ void VIEW3D_GGT_xform_gizmo(struct wmGizmoGroupType *gzgt); @@ -180,18 +193,6 @@ void ED_widgetgroup_gizmo2d_rotate_callbacks_set(struct wmGizmoGroupType *gzgt); #define SNAP_INCREMENTAL_ANGLE DEG2RAD(5.0) -void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]); -void ED_transform_calc_orientation_from_type_ex(const struct bContext *C, - float r_mat[3][3], - /* extra args */ - struct Scene *scene, - struct RegionView3D *rv3d, - struct Object *ob, - struct Object *obedit, - const short orientation_type, - int orientation_index_custom, - const int pivot_point); - struct TransformBounds { float center[3]; /* Center for transform widget. */ float min[3], max[3]; /* Boundbox of selection for transform widget. */ diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index c95f517b155..01bc59f71e7 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1938,7 +1938,7 @@ uiLayout *uiLayoutRadial(uiLayout *layout); /* templates */ void uiTemplateHeader(uiLayout *layout, struct bContext *C); void uiTemplateID(uiLayout *layout, - struct bContext *C, + const struct bContext *C, struct PointerRNA *ptr, const char *propname, const char *newop, @@ -2111,7 +2111,7 @@ void uiTemplateComponentMenu(uiLayout *layout, const char *name); void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); void uiTemplateCacheFile(uiLayout *layout, - struct bContext *C, + const struct bContext *C, struct PointerRNA *ptr, const char *propname); @@ -2144,7 +2144,7 @@ void uiTemplateNodeView(uiLayout *layout, struct bNodeSocket *input); void uiTemplateTextureUser(uiLayout *layout, struct bContext *C); void uiTemplateTextureShow(uiLayout *layout, - struct bContext *C, + const struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop); diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c index ace367fd513..c917ffb3f3e 100644 --- a/source/blender/editors/interface/interface_eyedropper_color.c +++ b/source/blender/editors/interface/interface_eyedropper_color.c @@ -138,11 +138,26 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]) { /* we could use some clever */ Main *bmain = CTX_data_main(C); - bScreen *screen = CTX_wm_screen(C); - ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + wmWindowManager *wm = CTX_wm_manager(C); const char *display_device = CTX_data_scene(C)->display_settings.display_device; struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device); + wmWindow *win = CTX_wm_window(C); + bScreen *screen = CTX_wm_screen(C); + ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + if (area == NULL) { + int mval[2] = {mx, my}; + if (WM_window_find_under_cursor(wm, NULL, win, mval, &win, mval)) { + mx = mval[0]; + my = mval[1]; + screen = WM_window_get_active_screen(win); + area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); + } + else { + win = NULL; + } + } + if (area) { if (area->spacetype == SPACE_IMAGE) { ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my); @@ -179,12 +194,15 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3]) } } - /* fallback to simple opengl picker */ - glReadBuffer(GL_FRONT); - glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col); - glReadBuffer(GL_BACK); - - IMB_colormanagement_display_to_scene_linear_v3(r_col, display); + if (win) { + /* Fallback to simple opengl picker. */ + int mval[2] = {mx, my}; + WM_window_pixel_sample_read(wm, win, mval, r_col); + IMB_colormanagement_display_to_scene_linear_v3(r_col, display); + } + else { + zero_v3(r_col); + } } /* sets the sample color RGB, maintaining A */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index c94a95890c0..deea3028354 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1603,8 +1603,8 @@ static void icon_draw_cache_texture_flush_ex(GLuint texture, GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR); GPU_shader_bind(shader); - int img_loc = GPU_shader_get_uniform_ensure(shader, "image"); - int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]"); + int img_loc = GPU_shader_get_uniform(shader, "image"); + int data_loc = GPU_shader_get_uniform(shader, "calls_data"); glUniform1i(img_loc, 0); glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache); @@ -1750,9 +1750,9 @@ static void icon_draw_texture(float x, GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha); } - glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), x1, y1, x2, y2); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x, y, x + w, y + h); + glUniform1i(GPU_shader_get_uniform(shader, "image"), 0); + glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2); + glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x, y, x + w, y + h); GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 9b59e4419c4..6bf2c721c20 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -799,7 +799,7 @@ static uiBut *template_id_def_new_but(uiBlock *block, return but; } -static void template_ID(bContext *C, +static void template_ID(const bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, @@ -1140,7 +1140,7 @@ ID *UI_context_active_but_get_tab_ID(bContext *C) } } -static void template_ID_tabs(bContext *C, +static void template_ID_tabs(const bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, @@ -1214,7 +1214,7 @@ static void template_ID_tabs(bContext *C, } static void ui_template_id(uiLayout *layout, - bContext *C, + const bContext *C, PointerRNA *ptr, const char *propname, const char *newop, @@ -1298,7 +1298,7 @@ static void ui_template_id(uiLayout *layout, } void uiTemplateID(uiLayout *layout, - bContext *C, + const bContext *C, PointerRNA *ptr, const char *propname, const char *newop, @@ -7523,7 +7523,10 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color) /** \name Cache File Template * \{ */ -void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname) +void uiTemplateCacheFile(uiLayout *layout, + const bContext *C, + PointerRNA *ptr, + const char *propname) { if (!ptr->data) { return; diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 551f7989d53..dc8ad858a9f 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -663,7 +663,7 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op) /* Switch out of edit mode to avoid being stuck in it (T54326). */ Object *obedit = CTX_data_edit_object(C); if (obedit) { - ED_object_mode_toggle(C, OB_MODE_EDIT); + ED_object_mode_set(C, OB_MODE_OBJECT); } bool ok = ABC_import(C, diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index bea44ee89f8..3786ed2789c 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -752,7 +752,7 @@ void ED_mask_draw_region( } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex( &state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL); diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f94cd778e13..5f5599b53df 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -2998,6 +2998,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) case MOUSEROTATE: case WHEELUPMOUSE: case WHEELDOWNMOUSE: + case NDOF_MOTION: return OPERATOR_PASS_THROUGH; case MOUSEMOVE: /* mouse moved somewhere to select another loop */ if (kcd->mode != MODE_PANNING) { diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 3861676c2cf..0f52911c603 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -515,6 +515,10 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op) static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) { + if (event->type == NDOF_MOTION) { + return OPERATOR_PASS_THROUGH; + } + RingSelOpData *lcd = op->customdata; float cuts = lcd->cuts; float smoothness = lcd->smoothness; @@ -606,7 +610,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) } handled = true; break; - case MOUSEMOVE: /* mouse moved somewhere to select another loop */ + case MOUSEMOVE: { + /* mouse moved somewhere to select another loop */ /* This is normally disabled for all modal operators. * This is an exception since mouse movement doesn't relate to numeric input. @@ -615,14 +620,16 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) #if 0 if (!has_numinput) #endif - { - lcd->vc.mval[0] = event->mval[0]; - lcd->vc.mval[1] = event->mval[1]; - loopcut_mouse_move(lcd, (int)lcd->cuts); + { + lcd->vc.mval[0] = event->mval[0]; + lcd->vc.mval[1] = event->mval[1]; + loopcut_mouse_move(lcd, (int)lcd->cuts); - ED_region_tag_redraw(lcd->region); - handled = true; - } break; + ED_region_tag_redraw(lcd->region); + handled = true; + } + break; + } } /* Modal numinput inactive, try to handle numeric inputs last... */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 53a557c5871..d522dcabae3 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1475,10 +1475,9 @@ static bool object_mode_set_poll(bContext *C) static int object_mode_set_exec(bContext *C, wmOperator *op) { - bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode"); + const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode"); Object *ob = CTX_data_active_object(C); eObjectMode mode = RNA_enum_get(op->ptr, "mode"); - eObjectMode restore_mode = ob->mode; const bool toggle = RNA_boolean_get(op->ptr, "toggle"); /* by default the operator assume is a mesh, but if gp object change mode */ @@ -1490,43 +1489,63 @@ static int object_mode_set_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } + /** + * Mode Switching Logic (internal details). + * + * Notes: + * - Code below avoids calling mode switching functions more than once, + * as this causes unnecessary calculations and undo steps to be added. + * - The previous mode (#Object.restore_mode) is object mode by default. + * + * Supported Cases: + * - Setting the mode (when the 'toggle' setting is off). + * - Toggle the mode: + * - Toggle between object mode and non-object mode property. + * - Toggle between the previous mode (#Object.restore_mode) and the mode property. + * - Toggle object mode. + * While this is similar to regular toggle, + * this operator depends on there being a previous mode set + * (this isn't bound to a key with the default key-map). + */ if (toggle == false) { if (ob->mode != mode) { - if (mode != OB_MODE_OBJECT) { - /* Enter new mode. */ - ED_object_mode_toggle(C, mode); - } - else { - ED_object_mode_compat_set(C, ob, mode, op->reports); - } + ED_object_mode_set_ex(C, mode, true, op->reports); } } else { - /* Exit current mode if it's not the mode we're setting */ - if (mode != OB_MODE_OBJECT) { - /* Enter new mode. */ - ED_object_mode_toggle(C, mode); - } - - /* Special case for Object mode! */ - if ((mode == OB_MODE_OBJECT) && (restore_mode == OB_MODE_OBJECT) && - (ob->restore_mode != OB_MODE_OBJECT)) { - ED_object_mode_toggle(C, ob->restore_mode); - } - else if (ob->mode == mode) { - /* For toggling, store old mode so we know what to go back to */ - ob->restore_mode = restore_mode; - } - else if ((ob->restore_mode != OB_MODE_OBJECT) && (ob->restore_mode != mode)) { - ED_object_mode_toggle(C, ob->restore_mode); + const eObjectMode mode_prev = ob->mode; + /* When toggling object mode, we always use the restore mode, + * otherwise there is nothing to do. */ + if (mode == OB_MODE_OBJECT) { + if (ob->mode != OB_MODE_OBJECT) { + if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) { + /* Store old mode so we know what to go back to. */ + ob->restore_mode = mode_prev; + } + } + else { + if (ob->restore_mode != OB_MODE_OBJECT) { + ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports); + } + } } - } - - /* if type is OB_GPENCIL, set cursor mode */ - if (ob->type == OB_GPENCIL) { - if (ob->data) { - bGPdata *gpd = (bGPdata *)ob->data; - ED_gpencil_setup_modes(C, gpd, ob->mode); + else { + /* Non-object modes, enter the 'mode' unless it's already set, + * in that case use restore mode. */ + if (ob->mode != mode) { + if (ED_object_mode_set_ex(C, mode, true, op->reports)) { + /* Store old mode so we know what to go back to. */ + ob->restore_mode = mode_prev; + } + } + else { + if (ob->restore_mode != OB_MODE_OBJECT) { + ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports); + } + else { + ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports); + } + } } } diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index f06b6a4db2a..fbd935c2e55 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -167,41 +167,6 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report return ok; } -void ED_object_mode_toggle(bContext *C, eObjectMode mode) -{ - if (mode != OB_MODE_OBJECT) { - const char *opstring = object_mode_op_string(mode); - - if (opstring) { - wmOperatorType *ot = WM_operatortype_find(opstring, false); - WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL); - } - } -} - -/* Wrapper for operator */ -void ED_object_mode_set(bContext *C, eObjectMode mode) -{ - wmWindowManager *wm = CTX_wm_manager(C); - wm->op_undo_depth++; - /* needed so we don't do undo pushes. */ - ED_object_mode_generic_enter(C, mode); - wm->op_undo_depth--; -} - -void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph) -{ - struct Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - FOREACH_OBJECT_BEGIN (view_layer, ob) { - if (ob->mode & OB_MODE_ALL_MODE_DATA) { - ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); - } - } - FOREACH_OBJECT_END; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -212,23 +177,50 @@ void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph) * * \{ */ -bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode) +bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports) { + wmWindowManager *wm = CTX_wm_manager(C); ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); if (ob == NULL) { - return (object_mode == OB_MODE_OBJECT); + return (mode == OB_MODE_OBJECT); + } + + if ((ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) { + mode = OB_MODE_EDIT_GPENCIL; } - if (ob->mode == object_mode) { + + if (ob->mode == mode) { return true; } - wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false); - PointerRNA ptr; - WM_operator_properties_create_ptr(&ptr, ot); - RNA_enum_set(&ptr, "mode", object_mode); - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr); - WM_operator_properties_free(&ptr); - return (ob->mode == object_mode); + + if (!ED_object_mode_compat_test(ob, mode)) { + return false; + } + + const char *opstring = object_mode_op_string((mode == OB_MODE_OBJECT) ? ob->mode : mode); + wmOperatorType *ot = WM_operatortype_find(opstring, false); + + if (!use_undo) { + wm->op_undo_depth++; + } + WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL); + if (!use_undo) { + wm->op_undo_depth--; + } + + if (ob->mode != mode) { + BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name); + return false; + } + + return true; +} + +bool ED_object_mode_set(bContext *C, eObjectMode mode) +{ + /* Don't do undo push by default, since this may be called by lower level code. */ + return ED_object_mode_set_ex(C, mode, true, NULL); } /** diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 11e9c396552..ca3a559ca1d 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2516,7 +2516,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op) ViewLayer *view_layer = CTX_data_view_layer(C); Collection *new_collection = (Collection *)collection->id.newid; - BKE_collection_child_add(bmain, scene->master_collection, new_collection); + BKE_collection_add_from_object(bmain, scene, obcollection, new_collection); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) { if (new_ob != NULL && new_ob->id.override_library != NULL) { if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) { @@ -2524,14 +2525,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op) base = BKE_view_layer_base_find(view_layer, new_ob); DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS); } - /* parent to 'collection' empty */ - /* Disabled for now, according to some artist this is probably not really useful anyway. - * And it breaks things like objects parented to bones - * (most likely due to missing proper setting of inverse parent matrix?)... */ - /* Note: we might even actually want to get rid of that instantiating empty... */ - if (0 && new_ob->parent == NULL) { - new_ob->parent = obcollection; - } + if (new_ob == (Object *)obact->id.newid) { /* TODO: is setting active needed? */ BKE_view_layer_base_select_and_set_active(view_layer, base); @@ -2546,9 +2540,9 @@ static int make_override_library_exec(bContext *C, wmOperator *op) } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; - /* obcollection is no more duplicollection-ing, - * it merely parents whole collection of overriding instantiated objects. */ - obcollection->instance_collection = NULL; + /* Remove the instance empty from this scene, the items now have an overriden collection + * instead. */ + ED_object_base_free_and_unlink(bmain, scene, obcollection); /* Also, we'd likely want to lock by default things like * transformations of implicitly overridden objects? */ diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 306adb36c52..3639cd64b7c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3235,12 +3235,12 @@ static void toggle_particle_cursor(bContext *C, int enable) ParticleEditSettings *pset = PE_settings(CTX_data_scene(C)); if (pset->paintcursor && !enable) { - WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor); + WM_paint_cursor_end(pset->paintcursor); pset->paintcursor = NULL; } else if (enable) { pset->paintcursor = WM_paint_cursor_activate( - CTX_wm_manager(C), SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL); + SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL); } } diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c index 5b363bdca78..205c04f54a9 100644 --- a/source/blender/editors/physics/particle_edit_undo.c +++ b/source/blender/editors/physics/particle_edit_undo.c @@ -253,7 +253,7 @@ static void particle_undosys_step_decode(struct bContext *C, { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); /* TODO(campbell): undo_system: use low-level API to set mode. */ - ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT); + ED_object_mode_set_ex(C, OB_MODE_PARTICLE_EDIT, false, NULL); BLI_assert(particle_undosys_poll(C)); ParticleUndoStep *us = (ParticleUndoStep *)us_p; diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index ddb345ab65e..a9380debbdc 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -83,7 +83,7 @@ static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state) /* To be used before calling immDrawPixelsTex * Default shader is GPU_SHADER_2D_IMAGE_COLOR * You can still set uniforms with : - * GPU_shader_uniform_int(shader, GPU_shader_get_uniform_ensure(shader, "name"), 0); + * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0); * */ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) { @@ -191,7 +191,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, /* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since * it does not need color. */ - if (state->shader != NULL && GPU_shader_get_uniform_ensure(state->shader, "color") != -1) { + if (state->shader != NULL && GPU_shader_get_uniform(state->shader, "color") != -1) { immUniformColor4fv((color) ? color : white); } diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c index 3edc51b038b..478a0adfd9a 100644 --- a/source/blender/editors/screen/workspace_edit.c +++ b/source/blender/editors/screen/workspace_edit.c @@ -83,8 +83,7 @@ static void workspace_change_update(WorkSpace *workspace_new, eObjectMode mode_new = workspace_new->object_mode; if (mode_old != mode_new) { - ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports); - ED_object_mode_toggle(C, mode_new); + ED_object_mode_set(C, mode_new); } #endif } @@ -175,7 +174,7 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager /* Automatic mode switching. */ if (workspace_new->object_mode != workspace_old->object_mode) { - ED_object_mode_generic_enter(C, workspace_new->object_mode); + ED_object_mode_set(C, workspace_new->object_mode); } return true; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 191a064a95c..4222a466a7b 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1674,23 +1674,13 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) /* Public API */ -void paint_cursor_start(bContext *C, bool (*poll)(bContext *C)) +void paint_cursor_start(Paint *p, bool (*poll)(bContext *C)) { - Paint *p = BKE_paint_get_active_from_context(C); - if (p && !p->paint_cursor) { p->paint_cursor = WM_paint_cursor_activate( - CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL); + SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL); } /* Invalidate the paint cursors. */ BKE_paint_invalidate_overlay_all(); } - -void paint_cursor_start_explicit(Paint *p, wmWindowManager *wm, bool (*poll)(bContext *C)) -{ - if (p && !p->paint_cursor) { - p->paint_cursor = WM_paint_cursor_activate( - wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL); - } -} diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index fd5018f76ff..6ad4d1e650a 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -511,12 +511,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo } if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) { - pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - image_paint_poll, - gradient_draw_line, - pop); + pop->cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop); } settings->imapaint.flag |= IMAGEPAINT_DRAWING; @@ -655,7 +651,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke) } if (pop->cursor) { - WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor); + WM_paint_cursor_end(pop->cursor); } ED_image_undo_push_end(); @@ -787,17 +783,17 @@ bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) static void toggle_paint_cursor(bContext *C, int enable) { - wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); ToolSettings *settings = scene->toolsettings; + Paint *p = &settings->imapaint.paint; - if (settings->imapaint.paintcursor && !enable) { - WM_paint_cursor_end(wm, settings->imapaint.paintcursor); - settings->imapaint.paintcursor = NULL; + if (p->paint_cursor && !enable) { + WM_paint_cursor_end(p->paint_cursor); + p->paint_cursor = NULL; paint_cursor_delete_textures(); } else if (enable) { - paint_cursor_start(C, image_paint_poll); + paint_cursor_start(p, image_paint_poll); } } @@ -827,7 +823,7 @@ void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene) if (enabled) { BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT); - paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll); + paint_cursor_start(&imapaint->paint, image_paint_poll); } else { paint_cursor_delete_textures(); diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index 018d7f72bb6..0d4e957c77b 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -90,10 +90,7 @@ void *paint_stroke_mode_data(struct PaintStroke *stroke); float paint_stroke_distance_get(struct PaintStroke *stroke); void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data); bool paint_poll(struct bContext *C); -void paint_cursor_start(struct bContext *C, bool (*poll)(struct bContext *C)); -void paint_cursor_start_explicit(struct Paint *p, - struct wmWindowManager *wm, - bool (*poll)(struct bContext *C)); +void paint_cursor_start(struct Paint *p, bool (*poll)(struct bContext *C)); void paint_cursor_delete_textures(void); /* paint_vertex.c */ diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 723ac58bc6e..2c6f708d82a 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -962,7 +962,7 @@ void paint_stroke_free(bContext *C, wmOperator *op) } if (stroke->stroke_cursor) { - WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor); + WM_paint_cursor_end(stroke->stroke_cursor); } BLI_freelistN(&stroke->line); @@ -1385,12 +1385,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (paint_supports_smooth_stroke(br, mode)) { - stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - paint_poll, - paint_draw_smooth_cursor, - stroke); + stroke->stroke_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_smooth_cursor, stroke); } stroke->stroke_init = true; @@ -1416,12 +1412,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) } if (br->flag & BRUSH_LINE) { - stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - paint_poll, - paint_draw_line_cursor, - stroke); + stroke->stroke_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_line_cursor, stroke); } first_dab = true; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 6172b77de07..6de54b3ae6a 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1193,12 +1193,8 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob) /** \name Enter Vertex/Weight Paint Mode * \{ */ -static void ed_vwpaintmode_enter_generic(Main *bmain, - Depsgraph *depsgraph, - wmWindowManager *wm, - Scene *scene, - Object *ob, - const eObjectMode mode_flag) +static void ed_vwpaintmode_enter_generic( + Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, const eObjectMode mode_flag) { ob->mode |= mode_flag; Mesh *me = BKE_mesh_from_object(ob); @@ -1214,7 +1210,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain, BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->vpaint); Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); - paint_cursor_start_explicit(paint, wm, vertex_paint_poll); + paint_cursor_start(paint, vertex_paint_poll); BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT); } else if (mode_flag == OB_MODE_WEIGHT_PAINT) { @@ -1222,7 +1218,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain, BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->wpaint); Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode); - paint_cursor_start_explicit(paint, wm, weight_paint_poll); + paint_cursor_start(paint, weight_paint_poll); BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT); /* weight paint specific */ @@ -1248,32 +1244,28 @@ static void ed_vwpaintmode_enter_generic(Main *bmain, DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); } -void ED_object_vpaintmode_enter_ex( - Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob) +void ED_object_vpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { - ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT); + ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_VERTEX_PAINT); } void ED_object_vpaintmode_enter(struct bContext *C, Depsgraph *depsgraph) { Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob); } -void ED_object_wpaintmode_enter_ex( - Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob) +void ED_object_wpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { - ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT); + ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_WEIGHT_PAINT); } void ED_object_wpaintmode_enter(struct bContext *C, Depsgraph *depsgraph) { Main *bmain = CTX_data_main(C); - wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob); } /** \} */ @@ -1384,8 +1376,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) if (depsgraph) { depsgraph = CTX_data_ensure_evaluated_depsgraph(C); } - wmWindowManager *wm = CTX_wm_manager(C); - ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob); BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint); } @@ -2651,8 +2642,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) if (depsgraph) { depsgraph = CTX_data_ensure_evaluated_depsgraph(C); } - wmWindowManager *wm = CTX_wm_manager(C); - ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob); BKE_paint_toolslots_brush_validate(bmain, &ts->vpaint->paint); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 4ad6bcc5d0f..b742ce91dd9 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -261,8 +261,15 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, int index) return !(ss->mvert[index].flag & ME_HIDE); case PBVH_BMESH: return !BM_elem_flag_test(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN); - case PBVH_GRIDS: - return true; + case PBVH_GRIDS: { + const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh); + const int grid_index = index / key->grid_area; + const int vertex_index = index - grid_index * key->grid_area; + BLI_bitmap **grid_hidden = BKE_pbvh_get_grid_visibility(ss->pbvh); + if (grid_hidden && grid_hidden[grid_index]) { + return !BLI_BITMAP_TEST(grid_hidden[grid_index], vertex_index); + } + } } return true; } @@ -7628,7 +7635,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain, Paint *paint = BKE_paint_get_active_from_paintmode(scene, PAINT_MODE_SCULPT); BKE_paint_init(bmain, scene, PAINT_MODE_SCULPT, PAINT_CURSOR_SCULPT); - paint_cursor_start_explicit(paint, bmain->wm.first, SCULPT_poll_view3d); + paint_cursor_start(paint, SCULPT_poll_view3d); /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes, * As long as no data was added that is not supported. */ @@ -7898,4 +7905,5 @@ void ED_operatortypes_sculpt(void) WM_operatortype_append(SCULPT_OT_face_sets_change_visibility); WM_operatortype_append(SCULPT_OT_face_sets_randomize_colors); WM_operatortype_append(SCULPT_OT_face_sets_init); + WM_operatortype_append(SCULPT_OT_cloth_filter); } diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index f0f6478d3a6..bfa657147fd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -91,7 +91,7 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co float SCULPT_automasking_factor_get(SculptSession *ss, int vert) { - if (ss->cache->automask) { + if (ss->cache && ss->cache->automask) { return ss->cache->automask[vert]; } else { diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index 6dac2b51645..3203282c30c 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -106,9 +106,11 @@ #define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024 #define CLOTH_SIMULATION_TIME_STEP 0.01f -static void cloth_brush_add_length_constraint(SculptSession *ss, const int v1, const int v2) +static void cloth_brush_add_length_constraint(SculptSession *ss, + SculptClothSimulation *cloth_sim, + const int v1, + const int v2) { - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v1 = v1; cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v2 = v2; cloth_sim->length_constraints[cloth_sim->tot_length_constraints].length = len_v3v3( @@ -133,12 +135,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex( SculptSession *ss = data->ob->sculpt; PBVHVertexIter vd; - const float radius = ss->cache->initial_radius; - const float limit = radius + (radius * data->brush->cloth_sim_limit); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (len_squared_v3v3(vd.co, ss->cache->initial_location) < limit * limit) { + if (len_squared_v3v3(vd.co, data->cloth_sim_initial_location) < + data->cloth_sim_radius * data->cloth_sim_radius) { SculptVertexNeighborIter ni; int build_indices[CLOTH_MAX_CONSTRAINTS_PER_VERTEX]; @@ -159,7 +160,8 @@ static void do_cloth_brush_build_constraints_task_cb_ex( for (int c_i = 0; c_i < tot_indices; c_i++) { for (int c_j = 0; c_j < tot_indices; c_j++) { if (c_i != c_j) { - cloth_brush_add_length_constraint(ss, build_indices[c_i], build_indices[c_j]); + cloth_brush_add_length_constraint( + ss, data->cloth_sim, build_indices[c_i], build_indices[c_j]); } } } @@ -192,11 +194,11 @@ static float cloth_brush_simulation_falloff_get(const Brush *brush, } } -static void cloth_brush_apply_force_to_vertex(SculptSession *ss, +static void cloth_brush_apply_force_to_vertex(SculptSession *UNUSED(ss), + SculptClothSimulation *cloth_sim, const float force[3], const int vertex_index) { - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; madd_v3_v3fl(cloth_sim->acceleration[vertex_index], force, 1.0f / cloth_sim->mass); } @@ -290,7 +292,6 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, float brush_disp[3]; float normal[3]; - if (vd.no) { normal_short_to_float_v3(normal, vd.no); } @@ -348,13 +349,15 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, madd_v3_v3fl(force, gravity, fade); - cloth_brush_apply_force_to_vertex(ss, force, vd.index); + cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); } } BKE_pbvh_vertex_iter_end; } -static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, Brush *brush) +static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, + const float cloth_mass, + const float cloth_damping) { const int totverts = SCULPT_vertex_count_get(ss); SculptClothSimulation *cloth_sim; @@ -373,8 +376,8 @@ static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, B cloth_sim->length_constraint_tweak = MEM_callocN(sizeof(float) * totverts, "cloth sim length tweak"); - cloth_sim->mass = brush->cloth_mass; - cloth_sim->damping = brush->cloth_damping; + cloth_sim->mass = cloth_mass; + cloth_sim->damping = cloth_damping; return cloth_sim; } @@ -386,12 +389,16 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( SculptSession *ss = data->ob->sculpt; const Brush *brush = data->brush; PBVHVertexIter vd; - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; + SculptClothSimulation *cloth_sim = data->cloth_sim; const float time_step = data->cloth_time_step; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - const float sim_factor = cloth_brush_simulation_falloff_get( - brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]); + const float sim_factor = ss->cache ? cloth_brush_simulation_falloff_get( + brush, + ss->cache->radius, + ss->cache->initial_location, + cloth_sim->init_pos[vd.index]) : + 1.0f; if (sim_factor > 0.0f) { int i = vd.index; float temp[3]; @@ -412,7 +419,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( copy_v3_fl(cloth_sim->acceleration[i], 0.0f); - copy_v3_v3(vd.co, ss->cache->cloth_sim->pos[vd.index]); + copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -424,7 +431,10 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( static void cloth_brush_build_nodes_constraints(Sculpt *sd, Object *ob, PBVHNode **nodes, - int totnode) + int totnode, + SculptClothSimulation *cloth_sim, + float initial_location[3], + const float radius) { Brush *brush = BKE_paint_brush(&sd->paint); @@ -440,6 +450,9 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, .ob = ob, .brush = brush, .nodes = nodes, + .cloth_sim = cloth_sim, + .cloth_sim_initial_location = initial_location, + .cloth_sim_radius = radius, }; BLI_task_parallel_range( 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings); @@ -480,10 +493,18 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss, const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) * SCULPT_automasking_factor_get(ss, v2); - const float sim_factor_v1 = cloth_brush_simulation_falloff_get( - brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v1]); - const float sim_factor_v2 = cloth_brush_simulation_falloff_get( - brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v2]); + const float sim_factor_v1 = ss->cache ? cloth_brush_simulation_falloff_get( + brush, + ss->cache->radius, + ss->cache->initial_location, + cloth_sim->init_pos[v1]) : + 1.0f; + const float sim_factor_v2 = ss->cache ? cloth_brush_simulation_falloff_get( + brush, + ss->cache->radius, + ss->cache->initial_location, + cloth_sim->init_pos[v2]) : + 1.0f; madd_v3_v3fl(cloth_sim->pos[v1], correction_vector_half, 1.0f * mask_v1 * sim_factor_v1); madd_v3_v3fl(cloth_sim->pos[v2], correction_vector_half, -1.0f * mask_v2 * sim_factor_v2); @@ -491,13 +512,12 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss, } } -static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) +static void cloth_brush_do_simulation_step( + Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - SculptClothSimulation *cloth_sim = ss->cache->cloth_sim; - /* Update the constraints. */ cloth_brush_satisfy_constraints(ss, brush, cloth_sim); @@ -508,6 +528,7 @@ static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **no .brush = brush, .nodes = nodes, .cloth_time_step = CLOTH_SIMULATION_TIME_STEP, + .cloth_sim = cloth_sim, }; TaskParallelSettings settings; @@ -608,7 +629,8 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode /* The simulation structure only needs to be created on the first symmetry pass. */ if (ss->cache->mirror_symmetry_pass == 0) { - ss->cache->cloth_sim = cloth_brush_simulation_create(ss, brush); + ss->cache->cloth_sim = cloth_brush_simulation_create( + ss, brush->cloth_mass, brush->cloth_damping); for (int i = 0; i < totverts; i++) { copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i)); copy_v3_v3(ss->cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i)); @@ -616,7 +638,10 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode } /* Build the constraints. */ - cloth_brush_build_nodes_constraints(sd, ob, nodes, totnode); + const float radius = ss->cache->initial_radius; + const float limit = radius + (radius * brush->cloth_sim_limit); + cloth_brush_build_nodes_constraints( + sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit); return; } @@ -630,7 +655,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode cloth_brush_apply_brush_foces(sd, ob, nodes, totnode); /* Update and write the simulation to the nodes. */ - cloth_brush_do_simulation_step(sd, ob, nodes, totnode); + cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); return; } @@ -706,3 +731,246 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr, immEnd(); } + +/* Cloth Filter. */ + +typedef enum eSculpClothFilterType { + CLOTH_FILTER_GRAVITY, + CLOTH_FILTER_INFLATE, + CLOTH_FILTER_EXPAND, + CLOTH_FILTER_PINCH, +} eSculptClothFilterType; + +static EnumPropertyItem prop_cloth_filter_type[] = { + {CLOTH_FILTER_GRAVITY, "GRAVITY", 0, "Gravity", "Applies gravity to the simulation"}, + {CLOTH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflates the cloth"}, + {CLOTH_FILTER_EXPAND, "EXPAND", 0, "Expand", "Expands the cloth's dimensions"}, + {CLOTH_FILTER_PINCH, + "PINCH", + 0, + "Pinch", + "Pinches the cloth to the point were the cursor was when the filter started"}, + {0, NULL, 0, NULL, NULL}, +}; + +static void cloth_filter_apply_forces_task_cb(void *__restrict userdata, + const int i, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + SculptThreadedTaskData *data = userdata; + Sculpt *sd = data->sd; + SculptSession *ss = data->ob->sculpt; + PBVHNode *node = data->nodes[i]; + + SculptClothSimulation *cloth_sim = ss->filter_cache->cloth_sim; + const int filter_type = data->filter_type; + + float sculpt_gravity[3] = {0.0f}; + if (sd->gravity_object) { + copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]); + } + else { + sculpt_gravity[2] = -1.0f; + } + mul_v3_fl(sculpt_gravity, sd->gravity_factor * data->filter_strength); + + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE) + { + float fade = vd.mask ? *vd.mask : 0.0f; + fade = 1.0f - fade; + float force[3] = {0.0f, 0.0f, 0.0f}; + + if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) { + if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) { + continue; + } + } + + switch (filter_type) { + case CLOTH_FILTER_GRAVITY: + force[2] = -data->filter_strength * fade; + break; + case CLOTH_FILTER_INFLATE: { + float normal[3]; + SCULPT_vertex_normal_get(ss, vd.index, normal); + mul_v3_v3fl(force, normal, fade * data->filter_strength); + } break; + case CLOTH_FILTER_EXPAND: + cloth_sim->length_constraint_tweak[vd.index] += fade * data->filter_strength * 0.01f; + zero_v3(force); + break; + case CLOTH_FILTER_PINCH: + sub_v3_v3v3(force, ss->filter_cache->cloth_sim_pinch_point, vd.co); + normalize_v3(force); + mul_v3_fl(force, fade * data->filter_strength); + break; + } + + add_v3_v3(force, sculpt_gravity); + + cloth_brush_apply_force_to_vertex(ss, cloth_sim, force, vd.index); + } + BKE_pbvh_vertex_iter_end; + + BKE_pbvh_node_mark_update(node); +} + +static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + SculptSession *ss = ob->sculpt; + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + int filter_type = RNA_enum_get(op->ptr, "type"); + float filter_strength = RNA_float_get(op->ptr, "strength"); + + if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { + SCULPT_filter_cache_free(ss); + SCULPT_undo_push_end(); + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); + return OPERATOR_FINISHED; + } + + if (event->type != MOUSEMOVE) { + return OPERATOR_RUNNING_MODAL; + } + + float len = event->prevclickx - event->mval[0]; + filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC; + + SCULPT_vertex_random_access_init(ss); + + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + + const int totverts = SCULPT_vertex_count_get(ss); + for (int i = 0; i < totverts; i++) { + copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i)); + } + + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .nodes = ss->filter_cache->nodes, + .filter_type = filter_type, + .filter_strength = filter_strength, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings( + &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); + BLI_task_parallel_range( + 0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings); + + /* Update and write the simulation to the nodes. */ + cloth_brush_do_simulation_step( + sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode); + + if (ss->deform_modifiers_active || ss->shapekey_active) { + SCULPT_flush_stroke_deform(sd, ob, true); + } + SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS); + return OPERATOR_RUNNING_MODAL; +} + +static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + Object *ob = CTX_data_active_object(C); + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + SculptSession *ss = ob->sculpt; + + /* Update the active vertex */ + float mouse[2]; + SculptCursorGeometryInfo sgi; + mouse[0] = event->mval[0]; + mouse[1] = event->mval[1]; + SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + + SCULPT_vertex_random_access_init(ss); + + /* Needs mask data to be available as it is used when solving the constraints. */ + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true); + + SCULPT_undo_push_begin("Cloth filter"); + SCULPT_filter_cache_init(ob, sd); + + const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass"); + const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping"); + ss->filter_cache->cloth_sim = cloth_brush_simulation_create(ss, cloth_mass, cloth_damping); + copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss)); + + const int totverts = SCULPT_vertex_count_get(ss); + for (int i = 0; i < totverts; i++) { + copy_v3_v3(ss->filter_cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i)); + copy_v3_v3(ss->filter_cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i)); + } + + float origin[3] = {0.0f, 0.0f, 0.0f}; + cloth_brush_build_nodes_constraints(sd, + ob, + ss->filter_cache->nodes, + ss->filter_cache->totnode, + ss->filter_cache->cloth_sim, + origin, + FLT_MAX); + + const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets"); + if (use_face_sets) { + ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss); + } + else { + ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE; + } + + WM_event_add_modal_handler(C, op); + return OPERATOR_RUNNING_MODAL; +} + +void SCULPT_OT_cloth_filter(struct wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Filter cloth"; + ot->idname = "SCULPT_OT_cloth_filter"; + ot->description = "Applies a cloth simulation deformation to the entire mesh"; + + /* API callbacks. */ + ot->invoke = sculpt_cloth_filter_invoke; + ot->modal = sculpt_cloth_filter_modal; + ot->poll = SCULPT_mode_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* RNA. */ + RNA_def_enum(ot->srna, + "type", + prop_cloth_filter_type, + CLOTH_FILTER_GRAVITY, + "Filter type", + "Operation that is going to be applied to the mesh"); + RNA_def_float( + ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f); + RNA_def_float(ot->srna, + "cloth_mass", + 1.0f, + 0.0f, + 2.0f, + "Cloth Mass", + "Mass of each simulation particle", + 0.0f, + 1.0f); + RNA_def_float(ot->srna, + "cloth_damping", + 0.0f, + 0.0f, + 1.0f, + "Cloth Damping", + "How much the applied forces are propagated through the cloth", + 0.0f, + 1.0f); + ot->prop = RNA_def_boolean(ot->srna, + "use_face_sets", + false, + "Use Face Sets", + "Apply the filter only to the Face Set under the cursor"); +} diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 7c438e9245b..58c9e1a569e 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -121,6 +121,9 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd) void SCULPT_filter_cache_free(SculptSession *ss) { + if (ss->filter_cache->cloth_sim) { + SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim); + } MEM_SAFE_FREE(ss->filter_cache->nodes); MEM_SAFE_FREE(ss->filter_cache->mask_update_it); MEM_SAFE_FREE(ss->filter_cache->prev_mask); @@ -565,8 +568,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent SCULPT_filter_cache_init(ob, sd); if (use_face_sets) { - ss->filter_cache->active_face_set = SCULPT_vertex_face_set_get(ss, - SCULPT_active_vertex_get(ss)); + ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss); } else { ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE; diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 6c217f66940..d7b221ae947 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -592,6 +592,9 @@ typedef struct SculptThreadedTaskData { float transform_mats[8][4][4]; float cloth_time_step; + SculptClothSimulation *cloth_sim; + float *cloth_sim_initial_location; + float cloth_sim_radius; float dirty_mask_min; float dirty_mask_max; @@ -837,6 +840,10 @@ typedef struct FilterCache { PBVHNode **nodes; int totnode; + /* Cloth filter. */ + SculptClothSimulation *cloth_sim; + float cloth_sim_pinch_point[3]; + /* mask expand iteration caches */ int mask_update_current_it; int mask_update_last_it; @@ -891,6 +898,9 @@ void SCULPT_OT_set_pivot_position(struct wmOperatorType *ot); /* Mesh Filter. */ void SCULPT_OT_mesh_filter(struct wmOperatorType *ot); +/* Cloth Filter. */ +void SCULPT_OT_cloth_filter(struct wmOperatorType *ot); + /* Mask filter and Dirty Mask. */ void SCULPT_OT_mask_filter(struct wmOperatorType *ot); void SCULPT_OT_dirty_mask(struct wmOperatorType *ot); diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index 35f4870fa12..56ba15bef70 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -401,6 +401,14 @@ typedef struct PoseFloodFillData { * that have the current face set. */ float fallback_origin[3]; int fallback_count; + + /* Face Set FK mode. */ + int *floodfill_it; + float *fk_weights; + int initial_face_set; + int masked_face_set_it; + int masked_face_set; + int target_face_set; } PoseFloodFillData; static bool pose_topology_floodfill_cb( @@ -806,6 +814,119 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets( return ik_chain; } +static bool pose_face_sets_fk_find_masked_floodfill_cb( + SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata) +{ + PoseFloodFillData *data = userdata; + + if (!is_duplicate) { + data->floodfill_it[to_v] = data->floodfill_it[from_v] + 1; + } + else { + data->floodfill_it[to_v] = data->floodfill_it[from_v]; + } + + const int to_face_set = SCULPT_vertex_face_set_get(ss, to_v); + if (SCULPT_vertex_has_unique_face_set(ss, to_v) && + !SCULPT_vertex_has_unique_face_set(ss, from_v) && + SCULPT_vertex_has_face_set(ss, from_v, to_face_set)) { + + if (data->floodfill_it[to_v] > data->masked_face_set_it) { + data->masked_face_set = to_face_set; + data->masked_face_set_it = data->floodfill_it[to_v]; + } + + if (data->target_face_set == SCULPT_FACE_SET_NONE) { + data->target_face_set = to_face_set; + } + } + + return SCULPT_vertex_has_face_set(ss, to_v, data->initial_face_set); +} + +static bool pose_face_sets_fk_set_weights_floodfill_cb( + SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata) +{ + PoseFloodFillData *data = userdata; + data->fk_weights[to_v] = 1.0f; + return !SCULPT_vertex_has_face_set(ss, to_v, data->masked_face_set); +} + +static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk( + Sculpt *sd, Object *ob, SculptSession *ss, const float radius, const float *initial_location) +{ + const int totvert = SCULPT_vertex_count_get(ss); + + SculptPoseIKChain *ik_chain = pose_ik_chain_new(1, totvert); + + const int active_vertex = SCULPT_active_vertex_get(ss); + const int active_face_set = SCULPT_active_face_set_get(ss); + + SculptFloodFill flood; + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_initial(&flood, active_vertex); + PoseFloodFillData fdata; + fdata.floodfill_it = MEM_calloc_arrayN(totvert, sizeof(int), "floodfill iteration"); + fdata.floodfill_it[active_vertex] = 1; + fdata.initial_face_set = active_face_set; + fdata.masked_face_set = SCULPT_FACE_SET_NONE; + fdata.target_face_set = SCULPT_FACE_SET_NONE; + fdata.masked_face_set_it = 0; + SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_find_masked_floodfill_cb, &fdata); + SCULPT_floodfill_free(&flood); + + int origin_count = 0; + float origin_acc[3] = {0.0f}; + for (int i = 0; i < totvert; i++) { + if (fdata.floodfill_it[i] != 0 && SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) && + SCULPT_vertex_has_face_set(ss, i, fdata.masked_face_set)) { + add_v3_v3(origin_acc, SCULPT_vertex_co_get(ss, i)); + origin_count++; + } + } + + int target_count = 0; + float target_acc[3] = {0.0f}; + if (fdata.target_face_set != fdata.masked_face_set) { + for (int i = 0; i < totvert; i++) { + if (fdata.floodfill_it[i] != 0 && + SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) && + SCULPT_vertex_has_face_set(ss, i, fdata.target_face_set)) { + add_v3_v3(target_acc, SCULPT_vertex_co_get(ss, i)); + target_count++; + } + } + } + + MEM_freeN(fdata.floodfill_it); + + if (origin_count > 0) { + copy_v3_v3(ik_chain->segments[0].orig, origin_acc); + mul_v3_fl(ik_chain->segments[0].orig, 1.0f / origin_count); + } + else { + zero_v3(ik_chain->segments[0].orig); + } + + if (target_count > 0) { + copy_v3_v3(ik_chain->segments[0].head, target_acc); + mul_v3_fl(ik_chain->segments[0].head, 1.0f / target_count); + sub_v3_v3v3(ik_chain->grab_delta_offset, ik_chain->segments[0].head, initial_location); + } + else { + copy_v3_v3(ik_chain->segments[0].head, initial_location); + } + + SCULPT_floodfill_init(ss, &flood); + SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius); + fdata.fk_weights = ik_chain->segments[0].weights; + SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_set_weights_floodfill_cb, &fdata); + SCULPT_floodfill_free(&flood); + + pose_ik_chain_origin_heads_init(ik_chain, ik_chain->segments[0].head); + return ik_chain; +} + SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, Object *ob, SculptSession *ss, @@ -820,6 +941,9 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd, case BRUSH_POSE_ORIGIN_FACE_SETS: return pose_ik_chain_init_face_sets(sd, ob, ss, br, radius); break; + case BRUSH_POSE_ORIGIN_FACE_SETS_FK: + return pose_ik_chain_init_face_sets_fk(sd, ob, ss, radius, initial_location); + break; } return NULL; } @@ -905,6 +1029,7 @@ static void sculpt_pose_do_rotate_deform(SculptSession *ss, Brush *brush) /* Calculate the IK target. */ copy_v3_v3(ik_target, ss->cache->true_location); add_v3_v3(ik_target, ss->cache->grab_delta); + add_v3_v3(ik_target, ik_chain->grab_delta_offset); /* Solve the IK positions. */ pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED); @@ -935,7 +1060,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - float grab_delta[3]; const ePaintSymmetryFlags symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL; /* The pose brush applies all enabled symmetry axis in a single iteration, so the rest can be @@ -945,7 +1069,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) } SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain; - copy_v3_v3(grab_delta, ss->cache->grab_delta); switch (brush->pose_deform_type) { case BRUSH_POSE_DEFORM_ROTATE_TWIST: @@ -999,7 +1122,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .ob = ob, .brush = brush, .nodes = nodes, - .grab_delta = grab_delta, }; TaskParallelSettings settings; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index e90122f2585..576b52a5cdd 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -490,7 +490,7 @@ void ACTION_OT_view_frame(wmOperatorType *ot) /* identifiers */ ot->name = "Go to Current Frame"; ot->idname = "ACTION_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* api callbacks */ ot->exec = actkeys_view_frame_exec; diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 5bf431be9f8..3dc5eca8a8b 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -545,7 +545,7 @@ static void template_texture_show(bContext *C, void *data_p, void *prop_p) } } -void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop) +void uiTemplateTextureShow(uiLayout *layout, const bContext *C, PointerRNA *ptr, PropertyRNA *prop) { /* button to quickly show texture in texture tab */ SpaceProperties *sbuts = CTX_wm_space_properties(C); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 8ffd2844f1a..a974ec612a9 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -385,7 +385,7 @@ void GRAPH_OT_view_frame(wmOperatorType *ot) /* identifiers */ ot->name = "Go to Current Frame"; ot->idname = "GRAPH_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* api callbacks */ ot->exec = graphkeys_view_frame_exec; diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 6037c1d2ec8..9040ca5e79c 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -476,7 +476,7 @@ static void sima_draw_zbuf_pixels( IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex( &state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL); @@ -524,7 +524,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex( &state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL); @@ -637,7 +637,7 @@ static void draw_image_buffer(const bContext *C, IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); display_buffer = IMB_display_buffer_acquire( diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 5668b88826e..e0c44c3a0ba 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -958,7 +958,7 @@ static void image_undosys_step_decode( } if (us->paint_mode == PAINT_MODE_TEXTURE_3D) { - ED_object_mode_set(C, OB_MODE_TEXTURE_PAINT); + ED_object_mode_set_ex(C, OB_MODE_TEXTURE_PAINT, false, NULL); } /* Refresh texture slots. */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index f68896e21d6..dec7a0fd93c 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -567,7 +567,7 @@ void NLA_OT_view_frame(wmOperatorType *ot) /* identifiers */ ot->name = "Go to Current Frame"; ot->idname = "NLA_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* api callbacks */ ot->exec = nlaedit_viewframe_exec; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 44003a5b9bc..01ac3a80871 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3638,7 +3638,7 @@ void draw_nodespace_back_pix(const bContext *C, IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle); immDrawPixelsTex(&state, x, diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 7bb62b0d1e2..d6efe683673 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -1427,9 +1427,9 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops, ten->name = id->name + 2; ten->directdata = lc; - /* Open by default. */ + /* Open by default, except linked collections, which may contain many elements. */ TreeStoreElem *tselem = TREESTORE(ten); - if (!tselem->used) { + if (!(tselem->used || ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id))) { tselem->flag &= ~TSE_CLOSED; } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5d8851d5e3d..1f06ab68516 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2299,10 +2299,10 @@ void draw_timeline_seq(const bContext *C, ARegion *region) cfra_flag |= DRAWCFRA_UNIT_SECONDS; } - /* Draw playhead. */ + /* Draw the current frame indicator. */ ANIM_draw_cfra(C, v2d, cfra_flag); - /* Draw overlap playhead. */ + /* Draw overlap frame frame indicator. */ if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) { int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? scene->ed->over_cfra : diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 232bb1d66e8..ea0d5785d22 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -214,20 +214,41 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports) } file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list"); + bool selected = false; /* Check for no selected strips */ + SEQP_BEGIN (ed, seq) { - if ((seq->flag & SELECT)) { - bool success = BKE_sequencer_proxy_rebuild_context( - pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue); - if (!success) { - BKE_reportf(reports, RPT_ERROR, "Could not build proxy for strip %s", seq->name); - } + if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META) || + (seq->flag & SELECT) == 0) { + continue; + } + + selected = true; + if (!(seq->flag & SEQ_USE_PROXY)) { + BKE_reportf(reports, RPT_WARNING, "Proxy is not enabled for %s, skipping.", seq->name); + continue; + } + else if (seq->strip->proxy->build_size_flags == 0) { + BKE_reportf(reports, RPT_WARNING, "Resolution is not selected for %s, skipping.", seq->name); + continue; + } + + bool success = BKE_sequencer_proxy_rebuild_context( + pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue); + + if (!success && (seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) != 0) { + BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping.", seq->name); } } SEQ_END; + if (!selected) { + BKE_reportf(reports, RPT_WARNING, "Select movie or image strips."); + return; + } + BLI_gset_free(file_list, MEM_freeN); - if (!WM_jobs_is_running(wm_job)) { + if (selected && !WM_jobs_is_running(wm_job)) { G.is_break = false; WM_jobs_start(CTX_wm_manager(C), wm_job); } @@ -290,7 +311,7 @@ static int mouse_frame_side(View2D *v2d, short mouse_x, int frame) mval[0] = mouse_x; mval[1] = 0; - /* Choose the side based on which side of the playhead the mouse is on. */ + /* Choose the side based on which side of the current frame the mouse is on. */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]); return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT; @@ -1355,7 +1376,7 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNU void SEQUENCER_OT_snap(struct wmOperatorType *ot) { /* Identifiers. */ - ot->name = "Snap Strips to Playhead"; + ot->name = "Snap Strips to the Current Frame"; ot->idname = "SEQUENCER_OT_snap"; ot->description = "Frame where selected strips will be snapped"; @@ -1706,7 +1727,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even mouse_x = event->mval[0]; } - /* Choose the side based on which side of the playhead the mouse is. */ + /* Choose the side based on which side of the current frame the mouse is. */ UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]); offset = mouseloc[0] - data->init_mouseloc[0]; @@ -2353,7 +2374,7 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot) "use_cursor_position", 0, "Use Cursor Position", - "Split at position of the cursor instead of playhead"); + "Split at position of the cursor instead of current frame"); prop = RNA_def_enum(ot->srna, "side", @@ -2955,7 +2976,7 @@ void SEQUENCER_OT_view_frame(wmOperatorType *ot) /* Identifiers. */ ot->name = "Go to Current Frame"; ot->idname = "SEQUENCER_OT_view_frame"; - ot->description = "Move the view to the playhead"; + ot->description = "Move the view to the current frame"; /* Api callbacks. */ ot->exec = sequencer_view_frame_exec; @@ -3757,12 +3778,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) SEQP_BEGIN (ed, seq) { if ((seq->flag & SELECT)) { - if (ELEM(seq->type, - SEQ_TYPE_MOVIE, - SEQ_TYPE_IMAGE, - SEQ_TYPE_META, - SEQ_TYPE_SCENE, - SEQ_TYPE_MULTICAM)) { + if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META)) { BKE_sequencer_proxy_set(seq, turnon); if (seq->strip->proxy == NULL) { continue; diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 708682cd04f..0e7e691c748 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -191,6 +191,7 @@ enum { SEQ_SELECT_LR_MOUSE, SEQ_SELECT_LR_LEFT, SEQ_SELECT_LR_RIGHT, + SEQ_SELECT_LR_OVERLAP, }; /* Defines used internally. */ diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index c5472ed88e5..2e6cd7f7442 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -412,6 +412,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) ret_value = OPERATOR_FINISHED; } + /* Select left, right or overlapping the current frame. */ else if (left_right != SEQ_SELECT_LR_NONE) { /* Use different logic for this. */ float x; @@ -420,20 +421,35 @@ static int sequencer_select_exec(bContext *C, wmOperator *op) } switch (left_right) { - case SEQ_SELECT_LR_MOUSE: + case SEQ_SELECT_LR_MOUSE: { + /* 10px margin around current frame to select under the current frame with mouse. */ + float margin = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask) * 10; x = UI_view2d_region_to_view_x(v2d, mval[0]); + if (x >= CFRA - margin && x <= CFRA + margin) { + x = CFRA; + } break; + } case SEQ_SELECT_LR_LEFT: x = CFRA - 1.0f; break; case SEQ_SELECT_LR_RIGHT: + x = CFRA + 1.0f; + break; + case SEQ_SELECT_LR_OVERLAP: default: x = CFRA; break; } SEQP_BEGIN (ed, seq) { - if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) { + /* Select overlapping the current frame. */ + if ((x == CFRA) && (seq->startdisp <= CFRA) && (seq->enddisp >= CFRA)) { + seq->flag = SELECT; + recurs_sel_seq(seq); + } + /* Select left or right. */ + else if ((x < CFRA && seq->enddisp <= CFRA) || (x > CFRA && seq->startdisp >= CFRA)) { seq->flag |= SELECT; recurs_sel_seq(seq); } @@ -627,8 +643,9 @@ void SEQUENCER_OT_select(wmOperatorType *ot) static const EnumPropertyItem sequencer_select_left_right_types[] = { {SEQ_SELECT_LR_NONE, "NONE", 0, "None", "Don't do left-right selection"}, {SEQ_SELECT_LR_MOUSE, "MOUSE", 0, "Mouse", "Use mouse position for selection"}, - {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select left"}, - {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"}, + {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select to the left of the current frame"}, + {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select to the right of the current frame"}, + {SEQ_SELECT_LR_OVERLAP, "OVERLAP", 0, "Overlap", "Select overlapping the current frame"}, {0, NULL, 0, NULL, NULL}, }; PropertyRNA *prop; diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index 1ec459ccfca..d823530fd89 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -25,11 +25,15 @@ #include "DNA_screen_types.h" +#include "BLI_listbase.h" + #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_report.h" +#include "RNA_access.h" +#include "RNA_define.h" #include "RNA_types.h" #include "UI_interface.h" @@ -41,11 +45,13 @@ #include "ED_userpref.h" +#include "MEM_guardedalloc.h" + /* -------------------------------------------------------------------- */ -/** \name Reset Default Theme +/** \name Reset Default Theme Operator * \{ */ -static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op)) +static int preferences_reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); UI_theme_init_default(); @@ -64,7 +70,7 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot) ot->description = "Reset to the default theme colors"; /* callbacks */ - ot->exec = reset_default_theme_exec; + ot->exec = preferences_reset_default_theme_exec; /* flags */ ot->flag = OPTYPE_REGISTER; @@ -72,7 +78,64 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Add Auto-Execution Path Operator + * \{ */ + +static int preferences_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); + BLI_addtail(&U.autoexec_paths, path_cmp); + U.runtime.is_dirty = true; + return OPERATOR_FINISHED; +} + +static void PREFERENCES_OT_autoexec_path_add(wmOperatorType *ot) +{ + ot->name = "Add Autoexec Path"; + ot->idname = "PREFERENCES_OT_autoexec_path_add"; + ot->description = "Add path to exclude from auto-execution"; + + ot->exec = preferences_autoexec_add_exec; + + ot->flag = OPTYPE_INTERNAL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Auto-Execution Path Operator + * \{ */ + +static int preferences_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) +{ + const int index = RNA_int_get(op->ptr, "index"); + bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); + if (path_cmp) { + BLI_freelinkN(&U.autoexec_paths, path_cmp); + U.runtime.is_dirty = true; + } + return OPERATOR_FINISHED; +} + +static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot) +{ + ot->name = "Remove Autoexec Path"; + ot->idname = "PREFERENCES_OT_autoexec_path_remove"; + ot->description = "Remove path to exclude from auto-execution"; + + ot->exec = preferences_autoexec_remove_exec; + + ot->flag = OPTYPE_INTERNAL; + + RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); +} + +/** \} */ + void ED_operatortypes_userpref(void) { WM_operatortype_append(PREFERENCES_OT_reset_default_theme); + WM_operatortype_append(PREFERENCES_OT_autoexec_path_add); + WM_operatortype_append(PREFERENCES_OT_autoexec_path_remove); } diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index f81b4bb09e2..cb87ddafea1 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -1642,7 +1642,7 @@ static int view3d_object_mode_menu(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) { - ED_object_mode_toggle(C, OB_MODE_POSE); + ED_object_mode_set(C, (ob->mode == OB_MODE_OBJECT) ? OB_MODE_POSE : OB_MODE_OBJECT); return OPERATOR_CANCELLED; } else { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 25678820050..edd75d8e561 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -3349,7 +3349,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name View Camera Center Operator +/** \name Frame Camera Bounds Operator * \{ */ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) @@ -3386,8 +3386,8 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) void VIEW3D_OT_view_center_camera(wmOperatorType *ot) { /* identifiers */ - ot->name = "View Camera Center"; - ot->description = "Center the camera view"; + ot->name = "Frame Camera Bounds"; + ot->description = "Center the camera view, resizing the view to fit its bounds"; ot->idname = "VIEW3D_OT_view_center_camera"; /* api callbacks */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 5fc65522fe6..79090bd633e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -49,6 +49,7 @@ #include "ED_space_api.h" #include "WM_api.h" +#include "WM_message.h" #include "WM_types.h" #include "UI_interface_icons.h" @@ -1195,7 +1196,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) stopConstraint(t); } else { - initSelectConstraint(t, event->shift); + initSelectConstraint(t); postSelectConstraint(t); } } @@ -1672,11 +1673,14 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) if (t->flag & T_MODAL) { /* do we check for parameter? */ if (transformModeUseSnap(t)) { - if (t->modifiers & MOD_SNAP) { - ts->snap_flag |= SCE_SNAP; - } - else { - ts->snap_flag &= ~SCE_SNAP; + if (!(t->modifiers & MOD_SNAP) != !(ts->snap_flag & SCE_SNAP)) { + if (t->modifiers & MOD_SNAP) { + ts->snap_flag |= SCE_SNAP; + } + else { + ts->snap_flag &= ~SCE_SNAP; + } + WM_msg_publish_rna_prop(t->mbus, &t->scene->id, ts, ToolSettings, use_snap); } } } @@ -1884,62 +1888,38 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); t->draw_handle_pixel = ED_region_draw_cb_activate( t->region->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_IMAGE) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_CLIP) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_NODE) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_GRAPH) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } else if (t->spacetype == SPACE_ACTION) { t->draw_handle_view = ED_region_draw_cb_activate( t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW); - t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C), - SPACE_TYPE_ANY, - RGN_TYPE_ANY, - transform_draw_cursor_poll, - transform_draw_cursor_draw, - t); + t->draw_handle_cursor = WM_paint_cursor_activate( + SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t); } createTransData(C, t); // make TransData structs from selection diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 7720660e2e8..192728f63d2 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -560,6 +560,7 @@ typedef struct TransInfo { void *view; /** Only valid (non null) during an operator called function. */ struct bContext *context; + struct wmMsgBus *mbus; struct ScrArea *area; struct ARegion *region; struct Depsgraph *depsgraph; @@ -610,56 +611,53 @@ enum { T_CURSOR = 1 << 5, /** Transform points, having no rotation/scale. */ T_POINTS = 1 << 6, - - /* empty slot - (1 << 7) */ - /** restrictions flags */ - T_NO_CONSTRAINT = 1 << 8, - T_NULL_ONE = 1 << 9, - T_NO_ZERO = 1 << 10, + T_NO_CONSTRAINT = 1 << 7, + T_NULL_ONE = 1 << 8, + T_NO_ZERO = 1 << 9, T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO, - T_PROP_EDIT = 1 << 11, - T_PROP_CONNECTED = 1 << 12, - T_PROP_PROJECTED = 1 << 13, + T_PROP_EDIT = 1 << 10, + T_PROP_CONNECTED = 1 << 11, + T_PROP_PROJECTED = 1 << 12, T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED, - T_V3D_ALIGN = 1 << 14, + T_V3D_ALIGN = 1 << 13, /** For 2d views like uv or fcurve. */ - T_2D_EDIT = 1 << 15, - T_CLIP_UV = 1 << 16, + T_2D_EDIT = 1 << 14, + T_CLIP_UV = 1 << 15, /** Auto-ik is on. */ - T_AUTOIK = 1 << 18, + T_AUTOIK = 1 << 16, /** Don't use mirror even if the data-block option is set. */ - T_NO_MIRROR = 1 << 19, + T_NO_MIRROR = 1 << 17, /** To indicate that the value set in the `value` parameter is the final * value of the transformation, modified only by the constrain. */ - T_INPUT_IS_VALUES_FINAL = 1 << 20, + T_INPUT_IS_VALUES_FINAL = 1 << 18, /** To specify if we save back settings at the end. */ - T_MODAL = 1 << 21, + T_MODAL = 1 << 19, /** No retopo. */ - T_NO_PROJECT = 1 << 22, + T_NO_PROJECT = 1 << 20, - T_RELEASE_CONFIRM = 1 << 23, + T_RELEASE_CONFIRM = 1 << 21, /** Alternative transformation. used to add offset to tracking markers. */ - T_ALT_TRANSFORM = 1 << 24, + T_ALT_TRANSFORM = 1 << 22, /** #TransInfo.center has been set, don't change it. */ - T_OVERRIDE_CENTER = 1 << 25, + T_OVERRIDE_CENTER = 1 << 23, - T_MODAL_CURSOR_SET = 1 << 26, + T_MODAL_CURSOR_SET = 1 << 24, - T_CLNOR_REBUILD = 1 << 27, + T_CLNOR_REBUILD = 1 << 25, /* Special Aftertrans. */ - T_AUTOMERGE = 1 << 28, - T_AUTOSPLIT = 1 << 29, + T_AUTOMERGE = 1 << 26, + T_AUTOSPLIT = 1 << 27, }; /** #TransInfo.modifiers */ @@ -706,40 +704,39 @@ enum { /** #TransData.flag */ enum { TD_SELECTED = 1 << 0, - TD_NOACTION = 1 << 2, - TD_USEQUAT = 1 << 3, - TD_NOTCONNECTED = 1 << 4, + TD_USEQUAT = 1 << 1, + TD_NOTCONNECTED = 1 << 2, /** Used for scaling of #MetaElem.rad */ - TD_SINGLESIZE = 1 << 5, + TD_SINGLESIZE = 1 << 3, /** Scale relative to individual element center */ - TD_INDIVIDUAL_SCALE = 1 << 8, - TD_NOCENTER = 1 << 9, + TD_INDIVIDUAL_SCALE = 1 << 4, + TD_NOCENTER = 1 << 5, /** #TransData.ext abused for particle key timing. */ - TD_NO_EXT = 1 << 10, + TD_NO_EXT = 1 << 6, /** don't transform this data */ - TD_SKIP = 1 << 11, + TD_SKIP = 1 << 7, /** if this is a bez triple, we need to restore the handles, * if this is set #TransData.hdata needs freeing */ - TD_BEZTRIPLE = 1 << 12, + TD_BEZTRIPLE = 1 << 8, /** when this is set, don't apply translation changes to this element */ - TD_NO_LOC = 1 << 13, + TD_NO_LOC = 1 << 9, /** For Graph Editor autosnap, indicates that point should not undergo autosnapping */ - TD_NOTIMESNAP = 1 << 14, + TD_NOTIMESNAP = 1 << 10, /** For Graph Editor - curves that can only have int-values * need their keyframes tagged with this. */ - TD_INTVALUES = 1 << 15, + TD_INTVALUES = 1 << 11, /** For editmode mirror, clamp axis to 0 */ - TD_MIRROR_EDGE_X = 1 << 16, - TD_MIRROR_EDGE_Y = 1 << 17, - TD_MIRROR_EDGE_Z = 1 << 18, + TD_MIRROR_EDGE_X = 1 << 12, + TD_MIRROR_EDGE_Y = 1 << 13, + TD_MIRROR_EDGE_Z = 1 << 14, /** For fcurve handles, move them along with their keyframes */ - TD_MOVEHANDLE1 = 1 << 19, - TD_MOVEHANDLE2 = 1 << 20, + TD_MOVEHANDLE1 = 1 << 15, + TD_MOVEHANDLE2 = 1 << 16, /** Exceptional case with pose bone rotating when a parent bone has 'Local Location' * option enabled and rotating also transforms it. */ - TD_PBONE_LOCAL_MTX_P = 1 << 21, + TD_PBONE_LOCAL_MTX_P = 1 << 17, /** Same as above but for a child bone. */ - TD_PBONE_LOCAL_MTX_C = 1 << 22, + TD_PBONE_LOCAL_MTX_C = 1 << 18, }; /** #TransSnap.status */ @@ -920,7 +917,7 @@ struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], const char *name, const bool overwrite); -bool applyTransformOrientation(const struct TransformOrientation *ts, +void applyTransformOrientation(const struct TransformOrientation *ts, float r_mat[3][3], char r_name[64]); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 0a6e0d6b7f5..0347522b8e8 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -829,11 +829,7 @@ static void drawObjectConstraint(TransInfo *t) } } - if (t->flag & T_OBJECT) { - copy_v3_v3(co, td->ob->obmat[3]); - axismtx = td->axismtx; - } - else if (t->flag & T_EDIT) { + if (t->flag & T_EDIT) { mul_v3_m4v3(co, tc->mat, td->center); mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx); @@ -880,21 +876,15 @@ void stopConstraint(TransInfo *t) /*------------------------- MMB Select -------------------------------*/ -void initSelectConstraint(TransInfo *t, bool force_global) +void initSelectConstraint(TransInfo *t) { - short orientation; - if (force_global) { - orientation = V3D_ORIENT_GLOBAL; - } - else { - if (t->orient_curr == 0) { - t->orient_curr = 1; - transform_orientations_current_set(t, t->orient_curr); - } - orientation = t->orient[t->orient_curr].type; + if (t->orient_curr == 0) { + t->orient_curr = 1; + transform_orientations_current_set(t, t->orient_curr); } - setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, ""); + short orientation = t->orient[t->orient_curr].type; + setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "%s"); setNearestAxis(t); } diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index b57a7599321..c41b9361ca4 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -35,7 +35,7 @@ void drawConstraint(TransInfo *t); void drawPropCircle(const struct bContext *C, TransInfo *t); void startConstraint(TransInfo *t); void stopConstraint(TransInfo *t); -void initSelectConstraint(TransInfo *t, bool force_global); +void initSelectConstraint(TransInfo *t); void selectConstraint(TransInfo *t); void postSelectConstraint(TransInfo *t); void setNearestAxis(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index b91542a80fc..ac69c2a60fe 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -827,10 +827,6 @@ void clipUVData(TransInfo *t) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (int a = 0; a < tc->data_len; a++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if ((td->flag & TD_SKIP) || (!td->loc)) { continue; } @@ -2390,10 +2386,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t) PTCacheID *pid; ob = td->ob; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index b1e69dde0ac..6de962a3ed1 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -174,9 +174,6 @@ static void clipMirrorModifier(TransInfo *t) int clip; float loc[3], iloc[3]; - if (td->flag & TD_NOACTION) { - break; - } if (td->loc == NULL) { break; } @@ -1068,11 +1065,6 @@ static void recalcData_objects(TransInfo *t) for (int i = 0; i < tc->data_len; i++, td++) { Object *ob = td->ob; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -1379,6 +1371,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve bGPdata *gpd = CTX_data_gpencil_data(C); PropertyRNA *prop; + t->mbus = CTX_wm_message_bus(C); t->depsgraph = CTX_data_depsgraph_pointer(C); t->scene = sce; t->view_layer = view_layer; @@ -1649,13 +1642,17 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } { - TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; short orient_type_set = -1; short orient_type_matrix_set = -1; - short orient_type_scene = orient_slot->type; - if (orient_type_scene == V3D_ORIENT_CUSTOM) { - const int index_custom = orient_slot->index_custom; - orient_type_scene += index_custom; + short orient_type_scene = V3D_ORIENT_GLOBAL; + + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; + orient_type_scene = orient_slot->type; + if (orient_type_scene == V3D_ORIENT_CUSTOM) { + const int index_custom = orient_slot->index_custom; + orient_type_scene += index_custom; + } } short orient_types[3]; @@ -1929,7 +1926,7 @@ void postTrans(bContext *C, TransInfo *t) ED_region_draw_cb_exit(t->region->type, t->draw_handle_pixel); } if (t->draw_handle_cursor) { - WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor); + WM_paint_cursor_end(t->draw_handle_cursor); } if (t->flag & T_MODAL_CURSOR_SET) { @@ -2408,19 +2405,11 @@ void calculatePropRatio(TransInfo *t) } else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) || (connected == 0 && td->rdist > t->prop_size)) { - /* - * The elements are sorted according to their dist member in the array, - * that means we can stop when it finds one element outside of the propsize. - * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed. - */ - td->factor = 0.0f; restoreElement(td); } else { /* Use rdist for falloff calculations, it is the real distance */ - td->flag &= ~TD_NOACTION; - if (connected) { dist = (t->prop_size - td->dist) / t->prop_size; } diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 04be7048791..ebc021cd983 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -635,101 +635,6 @@ bool gimbal_axis(Object *ob, float gmat[3][3]) return 0; } -void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3]) -{ - ARegion *region = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Object *obedit = CTX_data_edit_object(C); - RegionView3D *rv3d = region->regiondata; - Object *ob = OBACT(view_layer); - const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type; - const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom; - const int pivot_point = scene->toolsettings->transform_pivot_point; - - ED_transform_calc_orientation_from_type_ex( - C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point); -} - -void ED_transform_calc_orientation_from_type_ex(const bContext *C, - float r_mat[3][3], - /* extra args (can be accessed from context) */ - Scene *scene, - RegionView3D *rv3d, - Object *ob, - Object *obedit, - const short orientation_type, - int orientation_index_custom, - const int pivot_point) -{ - bool ok = false; - - switch (orientation_type) { - case V3D_ORIENT_GLOBAL: { - break; /* nothing to do */ - } - case V3D_ORIENT_GIMBAL: { - if (gimbal_axis(ob, r_mat)) { - ok = true; - break; - } - /* if not gimbal, fall through to normal */ - ATTR_FALLTHROUGH; - } - case V3D_ORIENT_NORMAL: { - if (obedit || ob->mode & OB_MODE_POSE) { - ED_getTransformOrientationMatrix(C, r_mat, pivot_point); - ok = true; - break; - } - /* no break we define 'normal' as 'local' in Object mode */ - ATTR_FALLTHROUGH; - } - case V3D_ORIENT_LOCAL: { - if (ob->mode & OB_MODE_POSE) { - /* each bone moves on its own local axis, but to avoid confusion, - * use the active pones axis for display [#33575], this works as expected on a single bone - * and users who select many bones will understand what's going on and what local means - * when they start transforming */ - ED_getTransformOrientationMatrix(C, r_mat, pivot_point); - ok = true; - break; - } - copy_m3_m4(r_mat, ob->obmat); - normalize_m3(r_mat); - ok = true; - break; - } - case V3D_ORIENT_VIEW: { - if (rv3d != NULL) { - copy_m3_m4(r_mat, rv3d->viewinv); - normalize_m3(r_mat); - ok = true; - } - break; - } - case V3D_ORIENT_CURSOR: { - BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat); - ok = true; - break; - } - case V3D_ORIENT_CUSTOM: - default: { - BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM); - TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find( - scene, orientation_index_custom); - if (applyTransformOrientation(custom_orientation, r_mat, NULL)) { - ok = true; - } - break; - } - } - - if (!ok) { - unit_m3(r_mat); - } -} - /* centroid, boundbox, of selection */ /* returns total items selected */ int ED_transform_calc_gizmo_stats(const bContext *C, diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c index 9bce793809b..4fd4599b940 100644 --- a/source/blender/editors/transform/transform_mode_align.c +++ b/source/blender/editors/transform/transform_mode_align.c @@ -52,10 +52,6 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) for (i = 0; i < tc->data_len; i++, td++) { float mat[3][3], invmat[3][3]; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_baketime.c b/source/blender/editors/transform/transform_mode_baketime.c index bb8fd0df13d..4e7fc3578ce 100644 --- a/source/blender/editors/transform/transform_mode_baketime.c +++ b/source/blender/editors/transform/transform_mode_baketime.c @@ -97,10 +97,6 @@ static void applyBakeTime(TransInfo *t, const int mval[2]) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c index c81049ac379..77850e74785 100644 --- a/source/blender/editors/transform/transform_mode_bbone_resize.c +++ b/source/blender/editors/transform/transform_mode_bbone_resize.c @@ -141,10 +141,6 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c index 721d226050a..3b51626b170 100644 --- a/source/blender/editors/transform/transform_mode_bend.c +++ b/source/blender/editors/transform/transform_mode_bend.c @@ -186,10 +186,6 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2])) float delta[3]; float fac, fac_scaled; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c index aa20a5ade95..7045d190478 100644 --- a/source/blender/editors/transform/transform_mode_boneenvelope.c +++ b/source/blender/editors/transform/transform_mode_boneenvelope.c @@ -73,10 +73,6 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_boneroll.c b/source/blender/editors/transform/transform_mode_boneroll.c index 0564a946148..1503519c519 100644 --- a/source/blender/editors/transform/transform_mode_boneroll.c +++ b/source/blender/editors/transform/transform_mode_boneroll.c @@ -75,10 +75,6 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c index 057f13ac068..84e4e950804 100644 --- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c @@ -73,10 +73,6 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c index 5db7895232c..399cec2d62c 100644 --- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c +++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c @@ -87,10 +87,6 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->val) { *td->val = td->ival + weight * td->factor; if (*td->val < 0.0f) { diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c index 4a92a57fef6..53c948c742b 100644 --- a/source/blender/editors/transform/transform_mode_edge_crease.c +++ b/source/blender/editors/transform/transform_mode_edge_crease.c @@ -87,10 +87,6 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 8690cd54a3b..c1cb4325c09 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -81,10 +81,6 @@ static void applySeqSlideValue(TransInfo *t, const float val[2]) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c index 267d297a31c..4712fb7ba01 100644 --- a/source/blender/editors/transform/transform_mode_gpopacity.c +++ b/source/blender/editors/transform/transform_mode_gpopacity.c @@ -73,10 +73,6 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c index 7c49d107703..ab9a0aa79ed 100644 --- a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c @@ -73,10 +73,6 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c index e42439920db..68f3abda85b 100644 --- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c +++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c @@ -78,10 +78,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -97,10 +93,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (td = tc->data, i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c index dae17374481..8d953610eb8 100644 --- a/source/blender/editors/transform/transform_mode_mirror.c +++ b/source/blender/editors/transform/transform_mode_mirror.c @@ -69,10 +69,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -93,10 +89,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c index 6eb038ea9b0..4a2f979ec38 100644 --- a/source/blender/editors/transform/transform_mode_push_pull.c +++ b/source/blender/editors/transform/transform_mode_push_pull.c @@ -82,10 +82,6 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index 00644b9bfdc..d919d5c889d 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -93,10 +93,6 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index 55c97630487..6480cb6c30e 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -82,10 +82,6 @@ static void applyRotationValue(TransInfo *t, FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c index 3eeb8a1e758..fa33c1550e7 100644 --- a/source/blender/editors/transform/transform_mode_shear.c +++ b/source/blender/editors/transform/transform_mode_shear.c @@ -165,11 +165,6 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { const float *center, *co; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index ed082e86b6d..78d3efa0d69 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -95,10 +95,6 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { float tdistance; /* temp dist */ - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c index b53dbb55c62..23d83050613 100644 --- a/source/blender/editors/transform/transform_mode_skin_resize.c +++ b/source/blender/editors/transform/transform_mode_skin_resize.c @@ -73,11 +73,6 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2])) for (i = 0; i < tc->data_len; i++, td++) { float tmat[3][3], smat[3][3]; float fsize[3]; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_tilt.c b/source/blender/editors/transform/transform_mode_tilt.c index 2f56f4bd162..ca0a8818477 100644 --- a/source/blender/editors/transform/transform_mode_tilt.c +++ b/source/blender/editors/transform/transform_mode_tilt.c @@ -77,10 +77,6 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2])) FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c index 841ccf41365..f6c5448a906 100644 --- a/source/blender/editors/transform/transform_mode_tosphere.c +++ b/source/blender/editors/transform/transform_mode_tosphere.c @@ -79,10 +79,6 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2])) TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { float tratio; - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c index c6e0b205204..ca5a749b275 100644 --- a/source/blender/editors/transform/transform_mode_trackball.c +++ b/source/blender/editors/transform/transform_mode_trackball.c @@ -63,10 +63,6 @@ static void applyTrackballValue(TransInfo *t, FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; for (i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 69552eda5bf..96820ca6385 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -236,10 +236,6 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) TransData *td = tc->data; for (int i = 0; i < tc->data_len; i++, td++) { - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 32269e1bacc..cd170b144d8 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -397,14 +397,12 @@ int BIF_countTransformOrientation(const bContext *C) return BLI_listbase_count(transform_orientations); } -bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name) +void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name) { if (r_name) { BLI_strncpy(r_name, ts->name, MAX_NAME); } copy_m3_m3(r_mat, ts->mat); - - return true; } /* Updates all `BONE_TRANSFORM` flags. @@ -438,82 +436,141 @@ static int armature_bone_transflags_update_recursive(bArmature *arm, return total; } -/* Sets the matrix of the specified space orientation. - * If the matrix cannot be obtained, an orientation different from the one - * informed is returned */ -short transform_orientation_matrix_get(bContext *C, - TransInfo *t, - const short orientation, - const float custom[3][3], - float r_spacemtx[3][3]) +void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3]) { - Object *ob = CTX_data_active_object(C); - Object *obedit = CTX_data_active_object(C); + ARegion *region = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obedit = CTX_data_edit_object(C); + RegionView3D *rv3d = region->regiondata; + Object *ob = OBACT(view_layer); + const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type; + const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom; + const int pivot_point = scene->toolsettings->transform_pivot_point; - switch (orientation) { - case V3D_ORIENT_GLOBAL: - unit_m3(r_spacemtx); - return V3D_ORIENT_GLOBAL; + ED_transform_calc_orientation_from_type_ex( + C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point); +} - case V3D_ORIENT_GIMBAL: - unit_m3(r_spacemtx); - if (ob && gimbal_axis(ob, r_spacemtx)) { +short ED_transform_calc_orientation_from_type_ex(const bContext *C, + float r_mat[3][3], + /* extra args (can be accessed from context) */ + Scene *scene, + RegionView3D *rv3d, + Object *ob, + Object *obedit, + const short orientation_type, + int orientation_index_custom, + const int pivot_point) +{ + switch (orientation_type) { + case V3D_ORIENT_GLOBAL: { + unit_m3(r_mat); + return V3D_ORIENT_GLOBAL; + } + case V3D_ORIENT_GIMBAL: { + if (gimbal_axis(ob, r_mat)) { return V3D_ORIENT_GIMBAL; } - ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */ - - case V3D_ORIENT_NORMAL: - if (obedit || (ob && ob->mode & OB_MODE_POSE)) { - ED_getTransformOrientationMatrix(C, r_spacemtx, t->around); + /* if not gimbal, fall through to normal */ + ATTR_FALLTHROUGH; + } + case V3D_ORIENT_NORMAL: { + if (obedit || ob->mode & OB_MODE_POSE) { + ED_getTransformOrientationMatrix(C, r_mat, pivot_point); return V3D_ORIENT_NORMAL; } - ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */ - - case V3D_ORIENT_LOCAL: + /* no break we define 'normal' as 'local' in Object mode */ + ATTR_FALLTHROUGH; + } + case V3D_ORIENT_LOCAL: { if (ob) { - copy_m3_m4(r_spacemtx, ob->obmat); - normalize_m3(r_spacemtx); + if (ob->mode & OB_MODE_POSE) { + /* each bone moves on its own local axis, but to avoid confusion, + * use the active pones axis for display [#33575], this works as expected on a single + * bone and users who select many bones will understand what's going on and what local + * means when they start transforming */ + ED_getTransformOrientationMatrix(C, r_mat, pivot_point); + } + else { + copy_m3_m4(r_mat, ob->obmat); + normalize_m3(r_mat); + } return V3D_ORIENT_LOCAL; } - unit_m3(r_spacemtx); + unit_m3(r_mat); return V3D_ORIENT_GLOBAL; - + } case V3D_ORIENT_VIEW: { - float mat[3][3]; - if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - RegionView3D *rv3d = t->region->regiondata; - copy_m3_m4(mat, rv3d->viewinv); - normalize_m3(mat); + if (rv3d != NULL) { + copy_m3_m4(r_mat, rv3d->viewinv); + normalize_m3(r_mat); } else { - unit_m3(mat); + unit_m3(r_mat); } - copy_m3_m3(r_spacemtx, mat); return V3D_ORIENT_VIEW; } - case V3D_ORIENT_CURSOR: - BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, r_spacemtx); + case V3D_ORIENT_CURSOR: { + BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat); return V3D_ORIENT_CURSOR; - - case V3D_ORIENT_CUSTOM_MATRIX: - copy_m3_m3(r_spacemtx, custom); - return V3D_ORIENT_CUSTOM_MATRIX; - + } + case V3D_ORIENT_CUSTOM_MATRIX: { + /* Do nothing. */; + break; + } case V3D_ORIENT_CUSTOM: - default: - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - TransformOrientation *ts = BKE_scene_transform_orientation_find( - t->scene, orientation - V3D_ORIENT_CUSTOM); - if (applyTransformOrientation(ts, r_spacemtx, t->spacename)) { - /* pass */ - } - else { - unit_m3(r_spacemtx); - } + default: { + BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM); + TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find( + scene, orientation_index_custom); + applyTransformOrientation(custom_orientation, r_mat, NULL); break; + } } - return orientation; + return orientation_type; +} + +/* Sets the matrix of the specified space orientation. + * If the matrix cannot be obtained, an orientation different from the one + * informed is returned */ +short transform_orientation_matrix_get(bContext *C, + TransInfo *t, + const short orientation, + const float custom[3][3], + float r_spacemtx[3][3]) +{ + if (orientation == V3D_ORIENT_CUSTOM_MATRIX) { + copy_m3_m3(r_spacemtx, custom); + return V3D_ORIENT_CUSTOM_MATRIX; + } + + if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { + Object *ob = CTX_data_active_object(C); + Object *obedit = CTX_data_active_object(C); + RegionView3D *rv3d = t->region->regiondata; + int orientation_index_custom = 0; + + if (orientation >= V3D_ORIENT_CUSTOM) { + orientation_index_custom = orientation - V3D_ORIENT_CUSTOM; + } + + return ED_transform_calc_orientation_from_type_ex( + C, + r_spacemtx, + /* extra args (can be accessed from context) */ + t->scene, + rv3d, + ob, + obedit, + orientation, + orientation_index_custom, + t->around); + } + + unit_m3(r_spacemtx); + return V3D_ORIENT_GLOBAL; } const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type) @@ -545,37 +602,7 @@ const char *transform_orientations_spacename_get(TransInfo *t, const short orien void transform_orientations_current_set(TransInfo *t, const short orient_index) { const short orientation = t->orient[orient_index].type; - const char *spacename; - switch (orientation) { - case V3D_ORIENT_GLOBAL: - spacename = TIP_("global"); - break; - case V3D_ORIENT_GIMBAL: - spacename = TIP_("gimbal"); - break; - case V3D_ORIENT_NORMAL: - spacename = TIP_("normal"); - break; - case V3D_ORIENT_LOCAL: - spacename = TIP_("local"); - break; - case V3D_ORIENT_VIEW: - spacename = TIP_("view"); - break; - case V3D_ORIENT_CURSOR: - spacename = TIP_("cursor"); - break; - case V3D_ORIENT_CUSTOM_MATRIX: - spacename = TIP_("custom"); - break; - case V3D_ORIENT_CUSTOM: - default: - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - TransformOrientation *ts = BKE_scene_transform_orientation_find( - t->scene, orientation - V3D_ORIENT_CUSTOM); - spacename = ts->name; - break; - } + const char *spacename = transform_orientations_spacename_get(t, orientation); BLI_strncpy(t->spacename, spacename, sizeof(t->spacename)); copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 50f525a324b..82602e7d828 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -306,11 +306,6 @@ void applyProject(TransInfo *t) for (i = 0; i < tc->data_len; i++, td++) { float iloc[3], loc[3], no[3]; float mval_fl[2]; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } @@ -417,11 +412,6 @@ void applyGridAbsolute(TransInfo *t) for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { float iloc[3], loc[3], tvec[3]; - - if (td->flag & TD_NOACTION) { - break; - } - if (td->flag & TD_SKIP) { continue; } diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 77bb0c1c785..c30b8d59dc0 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -104,7 +104,7 @@ typedef struct SnapObjectData { /* SNAP_EDIT_MESH */ BVHTreeFromEditMesh treedata_editmesh; float min[3], max[3]; - struct LinkNode **bvh_cache_p; + struct Mesh_Runtime *mesh_runtime; }; }; } SnapObjectData; @@ -144,6 +144,17 @@ struct SnapObjectContext { /** \} */ /* -------------------------------------------------------------------- */ +/** \name Utilities + * \{ */ + +static bool editmesh_eval_final_is_bmesh(const BMEditMesh *em) +{ + return (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Snap Object Data * \{ */ @@ -244,17 +255,17 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object return sod; } -static struct LinkNode **snap_object_data_editmesh_bvh_cache_get(Object *ob) +static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob) { BMEditMesh *em = BKE_editmesh_from_object(ob); if (em->mesh_eval_final) { - return &em->mesh_eval_final->runtime.bvh_cache; + return &em->mesh_eval_final->runtime; } if (em->mesh_eval_cage) { - return &em->mesh_eval_cage->runtime.bvh_cache; + return &em->mesh_eval_cage->runtime; } - return &((Mesh *)ob->data)->runtime.bvh_cache; + return &((Mesh *)ob->data)->runtime; } static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, @@ -291,23 +302,23 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, clear_cache = true; init = true; } - else if (sod->bvh_cache_p) { - if (sod->bvh_cache_p != snap_object_data_editmesh_bvh_cache_get(ob)) { + else if (sod->mesh_runtime) { + if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob)) { clear_cache = true; init = true; } else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached && - !bvhcache_has_tree(*sod->bvh_cache_p, sod->treedata_editmesh.tree)) { + !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->treedata_editmesh.tree)) { /* The tree is owned by the EditMesh and may have been freed since we last used! */ clear = true; } else if (sod->bvhtree[0] && sod->cached[0] && - !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[0])) { + !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[0])) { /* The tree is owned by the EditMesh and may have been freed since we last used! */ clear = true; } else if (sod->bvhtree[1] && sod->cached[1] && - !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[1])) { + !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[1])) { /* The tree is owned by the EditMesh and may have been freed since we last used! */ clear = true; } @@ -346,7 +357,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, bm_mesh_minmax(em->bm, sod->min, sod->max); } - sod->bvh_cache_p = snap_object_data_editmesh_bvh_cache_get(ob); + sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob); } return sod; @@ -359,7 +370,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx, * \{ */ typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx, - bool is_obedit, + bool use_obedit, bool use_backface_culling, Object *ob, float obmat[4][4], @@ -835,14 +846,19 @@ static bool raycastEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_looptri_ex( - treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL); + treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL); MEM_freeN(elem_mask); } else { /* Only cache if bvhtree is created without a mask. * This helps keep a standardized bvhtree in cache. */ - BKE_bvhtree_from_editmesh_get(treedata, em, 4, BVHTREE_FROM_EM_LOOPTRI, sod->bvh_cache_p); + BKE_bvhtree_from_editmesh_get(treedata, + em, + 4, + BVHTREE_FROM_EM_LOOPTRI, + &sod->mesh_runtime->bvh_cache, + sod->mesh_runtime->eval_mutex); } if (treedata->tree == NULL) { @@ -920,41 +936,52 @@ static bool raycastEditMesh(SnapObjectContext *sctx, return retval; } +struct RaycastObjUserData { + const float *ray_start; + const float *ray_dir; + uint ob_index; + /* read/write args */ + float *ray_depth; + /* return args */ + float *r_loc; + float *r_no; + int *r_index; + Object **r_ob; + float (*r_obmat)[4]; + ListBase *r_hit_list; + bool use_occlusion_test; + bool ret; +}; + /** * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; * * \note Duplicate args here are documented at #snapObjectsRay */ -static bool raycastObj(SnapObjectContext *sctx, - const float ray_start[3], - const float ray_dir[3], - Object *ob, - const float obmat[4][4], - const uint ob_index, - bool use_obedit, - bool use_occlusion_test, - bool use_backface_culling, - /* read/write args */ - float *ray_depth, - /* return args */ - float r_loc[3], - float r_no[3], - int *r_index, - Object **r_ob, - float r_obmat[4][4], - ListBase *r_hit_list) +static void raycast_obj_fn(SnapObjectContext *sctx, + bool use_obedit, + bool use_backface_culling, + Object *ob, + float obmat[4][4], + void *data) { + struct RaycastObjUserData *dt = data; + const uint ob_index = dt->ob_index++; + bool use_occlusion_test = dt->use_occlusion_test; + /* read/write args */ + float *ray_depth = dt->ray_depth; + bool retval = false; if (use_occlusion_test) { if (use_obedit && sctx->use_v3d && XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) { /* Use of occlude geometry in editing mode disabled. */ - return false; + return; } if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) { /* Do not hit objects that are in wire or bounding box * display mode. */ - return false; + return; } } @@ -963,22 +990,22 @@ static bool raycastObj(SnapObjectContext *sctx, Mesh *me = ob->data; bool use_hide = false; if (BKE_object_is_in_editmode(ob)) { - if (use_obedit) { + if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) { /* Operators only update the editmesh looptris of the original mesh. */ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); retval = raycastEditMesh(sctx, - ray_start, - ray_dir, + dt->ray_start, + dt->ray_dir, ob, em_orig, obmat, ob_index, use_backface_culling, ray_depth, - r_loc, - r_no, - r_index, - r_hit_list); + dt->r_loc, + dt->r_no, + dt->r_index, + dt->r_hit_list); break; } else { @@ -990,8 +1017,8 @@ static bool raycastObj(SnapObjectContext *sctx, } } retval = raycastMesh(sctx, - ray_start, - ray_dir, + dt->ray_start, + dt->ray_dir, ob, me, obmat, @@ -999,10 +1026,10 @@ static bool raycastObj(SnapObjectContext *sctx, use_hide, use_backface_culling, ray_depth, - r_loc, - r_no, - r_index, - r_hit_list); + dt->r_loc, + dt->r_no, + dt->r_index, + dt->r_hit_list); break; } case OB_CURVE: @@ -1011,8 +1038,8 @@ static bool raycastObj(SnapObjectContext *sctx, Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval) { retval = raycastMesh(sctx, - ray_start, - ray_dir, + dt->ray_start, + dt->ray_dir, ob, mesh_eval, obmat, @@ -1020,70 +1047,24 @@ static bool raycastObj(SnapObjectContext *sctx, false, use_backface_culling, ray_depth, - r_loc, - r_no, - r_index, - r_hit_list); + dt->r_loc, + dt->r_no, + dt->r_index, + dt->r_hit_list); break; } } } if (retval) { - if (r_ob) { - *r_ob = ob; + if (dt->r_ob) { + *dt->r_ob = ob; } - if (r_obmat) { - copy_m4_m4(r_obmat, obmat); + if (dt->r_obmat) { + copy_m4_m4(dt->r_obmat, obmat); } - return true; + dt->ret = true; } - - return false; -} - -struct RaycastObjUserData { - const float *ray_start; - const float *ray_dir; - uint ob_index; - /* read/write args */ - float *ray_depth; - /* return args */ - float *r_loc; - float *r_no; - int *r_index; - Object **r_ob; - float (*r_obmat)[4]; - ListBase *r_hit_list; - bool use_occlusion_test; - bool ret; -}; - -static void raycast_obj_cb(SnapObjectContext *sctx, - bool use_obedit, - bool use_backface_culling, - Object *ob, - float obmat[4][4], - void *data) -{ - struct RaycastObjUserData *dt = data; - - dt->ret |= raycastObj(sctx, - dt->ray_start, - dt->ray_dir, - ob, - obmat, - dt->ob_index++, - use_obedit, - dt->use_occlusion_test, - use_backface_culling, - dt->ray_depth, - dt->r_loc, - dt->r_no, - dt->r_index, - dt->r_ob, - dt->r_obmat, - dt->r_hit_list); } /** @@ -1144,7 +1125,7 @@ static bool raycastObjects(SnapObjectContext *sctx, .ret = false, }; - iter_snap_objects(sctx, depsgraph, params, raycast_obj_cb, &data); + iter_snap_objects(sctx, depsgraph, params, raycast_obj_fn, &data); return data.ret; } @@ -2524,11 +2505,16 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_verts_ex( - &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL); + &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL); MEM_freeN(verts_mask); } else { - BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, sod->bvh_cache_p); + BKE_bvhtree_from_editmesh_get(&treedata, + em, + 2, + BVHTREE_FROM_EM_VERTS, + &sod->mesh_runtime->bvh_cache, + (ThreadMutex *)sod->mesh_runtime->eval_mutex); } sod->bvhtree[0] = treedata.tree; sod->cached[0] = treedata.cached; @@ -2551,11 +2537,16 @@ static short snapEditMesh(SnapObjectContext *sctx, sctx->callbacks.edit_mesh.user_data); bvhtree_from_editmesh_edges_ex( - &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL); + &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL); MEM_freeN(edges_mask); } else { - BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, sod->bvh_cache_p); + BKE_bvhtree_from_editmesh_get(&treedata, + em, + 2, + BVHTREE_FROM_EM_EDGES, + &sod->mesh_runtime->bvh_cache, + sod->mesh_runtime->eval_mutex); } sod->bvhtree[1] = treedata.tree; sod->cached[1] = treedata.cached; @@ -2644,45 +2635,51 @@ static short snapEditMesh(SnapObjectContext *sctx, return 0; } +struct SnapObjUserData { + SnapData *snapdata; + /* read/write args */ + float *dist_px; + /* return args */ + float *r_loc; + float *r_no; + int *r_index; + Object **r_ob; + float (*r_obmat)[4]; + short ret; +}; + /** * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; * * \note Duplicate args here are documented at #snapObjectsRay */ -static short snapObject(SnapObjectContext *sctx, - SnapData *snapdata, - Object *ob, - float obmat[4][4], +static void sanp_obj_fn(SnapObjectContext *sctx, bool use_obedit, bool use_backface_culling, - /* read/write args */ - float *dist_px, - /* return args */ - float r_loc[3], - float r_no[3], - int *r_index, - Object **r_ob, - float r_obmat[4][4]) + Object *ob, + float obmat[4][4], + void *data) { + struct SnapObjUserData *dt = data; short retval = 0; switch (ob->type) { case OB_MESH: { Mesh *me = ob->data; if (BKE_object_is_in_editmode(ob)) { - if (use_obedit) { + if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) { /* Operators only update the editmesh looptris of the original mesh. */ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob)); retval = snapEditMesh(sctx, - snapdata, + dt->snapdata, ob, em_orig, obmat, use_backface_culling, - dist_px, - r_loc, - r_no, - r_index); + dt->dist_px, + dt->r_loc, + dt->r_no, + dt->r_index); break; } else { @@ -2694,99 +2691,66 @@ static short snapObject(SnapObjectContext *sctx, } else if (ob->dt == OB_BOUNDBOX) { /* Do not snap to objects that are in bounding box display mode */ - return 0; + return; } - retval = snapMesh( - sctx, snapdata, ob, me, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index); + retval = snapMesh(sctx, + dt->snapdata, + ob, + me, + obmat, + use_backface_culling, + dt->dist_px, + dt->r_loc, + dt->r_no, + dt->r_index); break; } case OB_ARMATURE: - retval = snapArmature(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index); + retval = snapArmature( + dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; case OB_CURVE: - retval = snapCurve(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index); + retval = snapCurve( + dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */ case OB_SURF: case OB_FONT: { Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); if (mesh_eval) { retval |= snapMesh(sctx, - snapdata, + dt->snapdata, ob, mesh_eval, obmat, use_backface_culling, - dist_px, - r_loc, - r_no, - r_index); + dt->dist_px, + dt->r_loc, + dt->r_no, + dt->r_index); } break; } case OB_EMPTY: - retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index); + retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; case OB_GPENCIL: - retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index); + retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; case OB_CAMERA: - retval = snapCamera(sctx, snapdata, ob, obmat, dist_px, r_loc, r_no, r_index); + retval = snapCamera( + sctx, dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index); break; } if (retval) { - if (r_ob) { - *r_ob = ob; + if (dt->r_ob) { + *dt->r_ob = ob; } - if (r_obmat) { - copy_m4_m4(r_obmat, obmat); + if (dt->r_obmat) { + copy_m4_m4(dt->r_obmat, obmat); } - return retval; - } - - return 0; -} - -struct SnapObjUserData { - SnapData *snapdata; - /* read/write args */ - float *dist_px; - /* return args */ - float *r_loc; - float *r_no; - int *r_index; - Object **r_ob; - float (*r_obmat)[4]; - short ret; -}; - -static void sanp_obj_cb(SnapObjectContext *sctx, - bool is_obedit, - bool use_backface_culling, - Object *ob, - float obmat[4][4], - void *data) -{ - struct SnapObjUserData *dt = data; - - short elem = snapObject(sctx, - dt->snapdata, - ob, - obmat, - is_obedit, - use_backface_culling, - /* read/write args */ - dt->dist_px, - /* return args */ - dt->r_loc, - dt->r_no, - dt->r_index, - dt->r_ob, - dt->r_obmat); - - if (elem) { - dt->ret = elem; + dt->ret = retval; } } @@ -2839,7 +2803,7 @@ static short snapObjectsRay(SnapObjectContext *sctx, .ret = 0, }; - iter_snap_objects(sctx, depsgraph, params, sanp_obj_cb, &data); + iter_snap_objects(sctx, depsgraph, params, sanp_obj_fn, &data); return data.ret; } diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index f8e19b742e4..af387e4f7c2 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -153,10 +153,10 @@ void ED_editors_init(bContext *C) ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, reports); } else if (mode == OB_MODE_VERTEX_PAINT) { - ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob); } else if (mode == OB_MODE_WEIGHT_PAINT) { - ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob); + ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob); } else { BLI_assert(0); @@ -174,7 +174,7 @@ void ED_editors_init(bContext *C) else { /* TODO(campbell): avoid operator calls. */ if (obact == ob) { - ED_object_mode_toggle(C, mode); + ED_object_mode_set(C, mode); } } } diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index f8cef95c776..897e2f13774 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -39,6 +39,7 @@ #include "../../draw/intern/draw_cache_impl.h" #include "BLI_math.h" +#include "BLI_task.h" #include "BLI_utildefines.h" #include "BKE_deform.h" @@ -206,8 +207,10 @@ static void uvedit_get_batches(Object *ob, else { batches->faces = NULL; } - - DRW_mesh_batch_cache_create_requested(ob, ob->data, scene, false, false); + struct TaskGraph *task_graph = BLI_task_graph_create(); + DRW_mesh_batch_cache_create_requested(task_graph, ob, ob->data, scene, false, false); + BLI_task_graph_work_and_wait(task_graph); + BLI_task_graph_free(task_graph); if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) { /* after create_requested we can load the actual areas */ @@ -229,7 +232,11 @@ static void draw_uvs_shadow(SpaceImage *sima, DRW_mesh_batch_cache_validate(me); GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me); - DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false); + + struct TaskGraph *task_graph = BLI_task_graph_create(); + DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false); + BLI_task_graph_work_and_wait(task_graph); + BLI_task_graph_free(task_graph); if (edges) { if (sima->flag & SI_SMOOTH_UV) { @@ -269,7 +276,10 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra DRW_mesh_batch_cache_validate(me); GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me); - DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false); + struct TaskGraph *task_graph = BLI_task_graph_create(); + DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false); + BLI_task_graph_work_and_wait(task_graph); + BLI_task_graph_free(task_graph); GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR); GPU_batch_uniform_4fv(geom, "color", col); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 78b6cfc44ac..22b51937083 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -71,6 +71,7 @@ #include "UI_resources.h" #include "UI_view2d.h" +#include "intern/math_base_inline.c" #include "uvedit_intern.h" /* -------------------------------------------------------------------- */ @@ -1843,11 +1844,12 @@ static void UV_OT_cursor_set(wmOperatorType *ot) static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) { + Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - int ret = OPERATOR_CANCELLED; const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT}; const bool mark_seams = RNA_boolean_get(op->ptr, "mark_seams"); const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp"); + bool changed_multi = false; uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( @@ -1858,111 +1860,76 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op) Mesh *me = (Mesh *)ob->data; BMEditMesh *em = me->edit_mesh; BMesh *bm = em->bm; - - UvVertMap *vmap; - BMEdge *editedge; BMIter iter; if (!EDBM_uv_check(em)) { continue; } - ret = OPERATOR_FINISHED; - - /* This code sets editvert->tmp.l to the index. This will be useful later on. */ - BM_mesh_elem_table_ensure(bm, BM_FACE); - vmap = BM_uv_vert_map_create(bm, limit, false, false); - - BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) { - /* flags to determine if we uv is separated from first editface match */ - char separated1 = 0, separated2; - /* set to denote edge must be flagged as seam */ - char faces_separated = 0; - /* flag to keep track if uv1 is disconnected from first editface match */ - char v1coincident = 1; - /* For use with v1coincident. v1coincident will change only if we've had commonFaces */ - int commonFaces = 0; - - BMFace *efa1, *efa2; - - UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter; - /* mv2cache stores the first of the list of coincident uv's for later comparison - * mv2sep holds the last separator and is copied to mv2cache - * when a hit is first found */ - UvMapVert *mv2cache = NULL, *mv2sep = NULL; - - mvinit1 = vmap->vert[BM_elem_index_get(editedge->v1)]; - if (mark_seams) { - BM_elem_flag_disable(editedge, BM_ELEM_SEAM); + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + bool changed = false; + + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, f)) { + continue; } - for (mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) { - if (mv1->separate && commonFaces) { - v1coincident = 0; + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (l_iter == l_iter->radial_next) { + continue; + } + if (!uvedit_edge_select_test(scene, l_iter, cd_loop_uv_offset)) { + continue; } - separated2 = 0; - efa1 = BM_face_at_index(bm, mv1->poly_index); - mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)]; + const MLoopUV *luv_curr = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset); - for (mv2 = mvinit2; mv2; mv2 = mv2->next) { - if (mv2->separate) { - mv2sep = mv2; + bool mark = false; + BMLoop *l_other = l_iter->radial_next; + do { + const MLoopUV *luv_other_curr = BM_ELEM_CD_GET_VOID_P(l_other, cd_loop_uv_offset); + const MLoopUV *luv_other_next = BM_ELEM_CD_GET_VOID_P(l_other->next, cd_loop_uv_offset); + if (l_iter->v != l_other->v) { + SWAP(const MLoopUV *, luv_other_curr, luv_other_next); } - efa2 = BM_face_at_index(bm, mv2->poly_index); - if (efa1 == efa2) { - /* if v1 is not coincident no point in comparing */ - if (v1coincident) { - /* have we found previously anything? */ - if (mv2cache) { - /* flag seam unless proved to be coincident with previous hit */ - separated2 = 1; - for (mviter = mv2cache; mviter; mviter = mviter->next) { - if (mviter->separate && mviter != mv2cache) { - break; - } - /* coincident with previous hit, do not flag seam */ - if (mviter == mv2) { - separated2 = 0; - } - } - } - /* First hit case, store the hit in the cache */ - else { - mv2cache = mv2sep; - commonFaces = 1; - } - } - else { - separated1 = 1; - } + if (!compare_ff(luv_curr->uv[0], luv_other_curr->uv[0], limit[0]) || + !compare_ff(luv_curr->uv[1], luv_other_curr->uv[1], limit[1]) || - if (separated1 || separated2) { - faces_separated = 1; - break; - } + !compare_ff(luv_next->uv[0], luv_other_next->uv[0], limit[0]) || + !compare_ff(luv_next->uv[1], luv_other_next->uv[1], limit[1])) { + mark = true; + break; } - } - } + } while ((l_other = l_other->radial_next) != l_iter); - if (faces_separated) { - if (mark_seams) { - BM_elem_flag_enable(editedge, BM_ELEM_SEAM); - } - if (mark_sharp) { - BM_elem_flag_disable(editedge, BM_ELEM_SMOOTH); + if (mark) { + if (mark_seams) { + BM_elem_flag_enable(l_iter->e, BM_ELEM_SEAM); + } + if (mark_sharp) { + BM_elem_flag_disable(l_iter->e, BM_ELEM_SMOOTH); + } + changed = true; } - } + } while ((l_iter = l_iter->next) != l_first); } - BM_uv_vert_map_free(vmap); - - DEG_id_tag_update(&me->id, 0); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + if (changed) { + changed_multi = true; + DEG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, me); + } } MEM_freeN(objects); - return ret; + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static void UV_OT_seams_from_islands(wmOperatorType *ot) diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 3fb48292000..ab507d852e8 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -50,7 +50,7 @@ void GPU_paint_set_mipmap(struct Main *bmain, bool mipmap); /* Anisotropic filtering settings * - these will free textures on changes */ -void GPU_set_anisotropic(struct Main *bmain, float value); +void GPU_set_anisotropic(float value); float GPU_get_anisotropic(void); /* Image updates and free diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 337c0b03308..eeb2d2caef2 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -29,6 +29,8 @@ #include "BLI_sys_types.h" /* for bool */ +#include "GPU_texture.h" /* for eGPUSamplerState */ + #ifdef __cplusplus extern "C" { #endif @@ -138,8 +140,14 @@ typedef enum eGPUMaterialStatus { GPUNodeLink *GPU_constant(const float *num); GPUNodeLink *GPU_uniform(const float *num); GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name); -GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser); -GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser); +GPUNodeLink *GPU_image(GPUMaterial *mat, + struct Image *ima, + struct ImageUser *iuser, + eGPUSamplerState sampler_state); +GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, + struct Image *ima, + struct ImageUser *iuser, + eGPUSamplerState sampler_state); GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser); GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer); GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name); @@ -190,6 +198,7 @@ void GPU_materials_free(struct Main *bmain); struct Scene *GPU_material_scene(GPUMaterial *material); struct GPUPass *GPU_material_get_pass(GPUMaterial *material); +struct GPUShader *GPU_material_get_shader(GPUMaterial *material); struct Material *GPU_material_get_material(GPUMaterial *material); eGPUMaterialStatus GPU_material_status(GPUMaterial *mat); @@ -228,6 +237,7 @@ typedef struct GPUMaterialTexture { char sampler_name[32]; /* Name of sampler in GLSL. */ char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */ int users; + int sampler_state; /* eGPUSamplerState */ } GPUMaterialTexture; typedef struct GPUMaterialVolumeGrid { diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 0e382f2225f..40bae88f46d 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -92,16 +92,17 @@ void *GPU_shader_get_interface(GPUShader *shader); void GPU_shader_set_srgb_uniform(const struct GPUShaderInterface *interface); int GPU_shader_get_uniform(GPUShader *shader, const char *name); -int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name); int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin); int GPU_shader_get_uniform_block(GPUShader *shader, const char *name); + +int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name); +int GPU_shader_get_texture_binding(GPUShader *shader, const char *name); + void GPU_shader_uniform_vector( GPUShader *shader, int location, int length, int arraysize, const float *value); void GPU_shader_uniform_vector_int( GPUShader *shader, int location, int length, int arraysize, const int *value); -void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo); -void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex); void GPU_shader_uniform_float(GPUShader *shader, int location, float value); void GPU_shader_uniform_int(GPUShader *shader, int location, int value); diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h index 3e7bad409a3..319a79a9e42 100644 --- a/source/blender/gpu/GPU_shader_interface.h +++ b/source/blender/gpu/GPU_shader_interface.h @@ -64,41 +64,40 @@ typedef enum { } GPUUniformBuiltin; typedef struct GPUShaderInput { - struct GPUShaderInput *next; uint32_t name_offset; - uint name_hash; - /** Only for uniform inputs. */ - GPUUniformBuiltin builtin_type; - /** Only for attribute inputs. */ - uint32_t gl_type; - /** Only for attribute inputs. */ - int32_t size; + uint32_t name_hash; int32_t location; + /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */ + int32_t binding; } GPUShaderInput; -#define GPU_NUM_SHADERINTERFACE_BUCKETS 257 #define GPU_SHADERINTERFACE_REF_ALLOC_COUNT 16 typedef struct GPUShaderInterface { - int32_t program; - uint32_t name_buffer_offset; - GPUShaderInput *attr_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; - GPUShaderInput *uniform_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; - GPUShaderInput *ubo_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; - GPUShaderInput *builtin_uniforms[GPU_NUM_UNIFORMS]; + /** Buffer containing all inputs names separated by '\0'. */ char *name_buffer; - struct GPUBatch **batches; /* references to batches using this interface */ + /** Reference to GPUBatches using this interface */ + struct GPUBatch **batches; uint batches_len; - /** All enabled attributes in this shader. Used to set default values for unbound attributes. */ + /** Input counts. */ + uint attribute_len; + uint ubo_len; + uint uniform_len; + /** Enabled bindpoints that needs to be fed with data. */ uint16_t enabled_attr_mask; + uint16_t enabled_ubo_mask; + uint64_t enabled_tex_mask; + /** Opengl Location of builtin uniforms. Fast access, no lookup needed. */ + /* TODO replace by location only array. */ + GPUShaderInput builtins[GPU_NUM_UNIFORMS]; + /** Flat array. In this order: Attributes, Ubos, Uniforms. */ + GPUShaderInput inputs[0]; } GPUShaderInterface; GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id); void GPU_shaderinterface_discard(GPUShaderInterface *); const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *, const char *name); -const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *, - const char *name); const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *, GPUUniformBuiltin); const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *, const char *name); diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 3d99a3c8a56..a13f61177e6 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -41,6 +41,31 @@ struct PreviewImage; struct GPUFrameBuffer; typedef struct GPUTexture GPUTexture; +/* GPU Samplers state + * - Specify the sampler state to bind a texture with. + * - Internally used by textures. + * - All states are created at startup to avoid runtime costs. + */ + +typedef enum eGPUSamplerState { + GPU_SAMPLER_FILTER = (1 << 0), + GPU_SAMPLER_MIPMAP = (1 << 1), + GPU_SAMPLER_REPEAT_S = (1 << 2), + GPU_SAMPLER_REPEAT_T = (1 << 3), + GPU_SAMPLER_REPEAT_R = (1 << 4), + GPU_SAMPLER_CLAMP_BORDER = (1 << 5), /* Clamp to border color instead of border texel. */ + GPU_SAMPLER_COMPARE = (1 << 6), + GPU_SAMPLER_ANISO = (1 << 7), + /* Don't use that. */ + GPU_SAMPLER_MAX = (1 << 8), +} eGPUSamplerState; + +#define GPU_SAMPLER_DEFAULT GPU_SAMPLER_FILTER +#define GPU_SAMPLER_REPEAT (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R) + +void GPU_samplers_init(void); +void GPU_samplers_free(void); + /* GPU Texture * - always returns unsigned char RGBA textures * - if texture with non square dimensions is created, depending on the @@ -236,8 +261,9 @@ void GPU_texture_free(GPUTexture *tex); void GPU_texture_ref(GPUTexture *tex); void GPU_texture_bind(GPUTexture *tex, int number); +void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number); void GPU_texture_unbind(GPUTexture *tex); -int GPU_texture_bound_number(GPUTexture *tex); +void GPU_texture_unbind_all(void); void GPU_texture_copy(GPUTexture *dst, GPUTexture *src); diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h index 7adad2ff831..61b14a4c5c0 100644 --- a/source/blender/gpu/GPU_vertex_format.h +++ b/source/blender/gpu/GPU_vertex_format.h @@ -101,12 +101,11 @@ typedef struct GPUVertFormat { char names[GPU_VERT_ATTR_NAMES_BUF_LEN]; } GPUVertFormat; -struct GPUShaderInterface; +struct GPUShader; void GPU_vertformat_clear(GPUVertFormat *); void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src); -void GPU_vertformat_from_interface(GPUVertFormat *format, - const struct GPUShaderInterface *shaderface); +void GPU_vertformat_from_shader(GPUVertFormat *format, const struct GPUShader *shader); uint GPU_vertformat_attr_add( GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode); diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 3e0a1e57664..5f77f13c135 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -375,7 +375,7 @@ void GPU_batch_program_set_no_use(GPUBatch *batch, const GPUShaderInterface *shaderface) { #if TRUST_NO_ONE - assert(glIsProgram(shaderface->program)); + assert(glIsProgram(program)); assert(batch->program_in_use == 0); #endif batch->interface = shaderface; @@ -551,11 +551,11 @@ void GPU_batch_program_use_end(GPUBatch *batch) #if TRUST_NO_ONE # define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name); \ assert(uniform); #else # define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name); #endif void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, uint value) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 8a46e24d459..c1e7933d7ba 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1160,7 +1160,7 @@ static int count_active_texture_sampler(GPUShader *shader, char *source) if (*code != '\0') { char sampler_name[64]; code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name)); - int id = GPU_shader_get_uniform_ensure(shader, sampler_name); + int id = GPU_shader_get_uniform(shader, sampler_name); if (id == -1) { continue; diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 7871907a7d4..1c346217e9f 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -158,10 +158,10 @@ static GLenum gpu_get_mipmap_filter(bool mag) } /* Anisotropic filtering settings */ -void GPU_set_anisotropic(Main *bmain, float value) +void GPU_set_anisotropic(float value) { if (GTS.anisotropic != value) { - GPU_free_images(bmain); + GPU_samplers_free(); /* Clamp value to the maximum value the graphics card supports */ const float max = GPU_max_texture_anisotropy(); @@ -170,6 +170,8 @@ void GPU_set_anisotropic(Main *bmain, float value) } GTS.anisotropic = value; + + GPU_samplers_init(); } } @@ -449,22 +451,12 @@ static uint gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf) BKE_image_release_ibuf(ima, ibuf, NULL); } - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - if (GPU_get_mipmap()) { glGenerateMipmap(GL_TEXTURE_2D_ARRAY); - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); if (ima) { ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; } } - else { - glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - - if (GLEW_EXT_texture_filter_anisotropic) { - glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); - } glBindTexture(GL_TEXTURE_2D_ARRAY, 0); @@ -1098,18 +1090,12 @@ void GPU_create_gl_tex(uint *bind, GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); } - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - if (GPU_get_mipmap() && mipmap) { glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); if (ima) { ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; } } - else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } } else if (textarget == GL_TEXTURE_CUBE_MAP) { int w = rectw / 3, h = recth / 2; @@ -1132,22 +1118,13 @@ void GPU_create_gl_tex(uint *bind, } } - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - if (GPU_get_mipmap() && mipmap) { glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); if (ima) { ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; } } - else { - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); gpu_del_cube_map(cube_map); } @@ -1156,10 +1133,6 @@ void GPU_create_gl_tex(uint *bind, } } - if (GLEW_EXT_texture_filter_anisotropic) { - glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); - } - glBindTexture(textarget, 0); if (ibuf) { @@ -1211,10 +1184,6 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - if (GLEW_EXT_texture_filter_anisotropic) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); - } - blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16; for (i = 0; i < ibuf->dds_data.nummipmaps && (width || height); i++) { if (width == 0) { diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index ff745787630..8f911f3c77d 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -355,11 +355,13 @@ void gpu_extensions_init(void) } GPU_invalid_tex_init(); + GPU_samplers_init(); } void gpu_extensions_exit(void) { GPU_invalid_tex_free(); + GPU_samplers_free(); } bool GPU_mem_stats_supported(void) diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index d95904c0007..b4cc432dd36 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -759,13 +759,11 @@ void immVertex2iv(uint attr_id, const int data[2]) #if 0 # if TRUST_NO_ONE # define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \ - name); \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \ assert(uniform); # else # define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \ - name); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); # endif #else /* NOTE: It is possible to have uniform fully optimized out from the shader. @@ -773,8 +771,7 @@ void immVertex2iv(uint attr_id, const int data[2]) * TODO(sergey): How can we detect existing-but-optimized-out uniform but still * catch typos in uniform names passed to immUniform*() functions? */ # define GET_UNIFORM \ - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \ - name); \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \ if (uniform == NULL) \ return; #endif @@ -812,20 +809,9 @@ void immUniform3fv(const char *name, const float data[3]) /* can increase this limit or move to another file */ #define MAX_UNIFORM_NAME_LEN 60 -void immUniformArray3fv(const char *bare_name, const float *data, int count) +/* Note array index is not supported for name (i.e: "array[0]"). */ +void immUniformArray3fv(const char *name, const float *data, int count) { - /* look up "name[0]" when given "name" */ - const size_t len = strlen(bare_name); -#if TRUST_NO_ONE - assert(len <= MAX_UNIFORM_NAME_LEN); -#endif - char name[MAX_UNIFORM_NAME_LEN]; - strcpy(name, bare_name); - name[len + 0] = '['; - name[len + 1] = '0'; - name[len + 2] = ']'; - name[len + 3] = '\0'; - GET_UNIFORM glUniform3fv(uniform->location, count, data); } @@ -842,20 +828,9 @@ void immUniform4fv(const char *name, const float data[4]) glUniform4fv(uniform->location, 1, data); } -void immUniformArray4fv(const char *bare_name, const float *data, int count) +/* Note array index is not supported for name (i.e: "array[0]"). */ +void immUniformArray4fv(const char *name, const float *data, int count) { - /* look up "name[0]" when given "name" */ - const size_t len = strlen(bare_name); -#if TRUST_NO_ONE - assert(len <= MAX_UNIFORM_NAME_LEN); -#endif - char name[MAX_UNIFORM_NAME_LEN]; - strcpy(name, bare_name); - name[len + 0] = '['; - name[len + 1] = '0'; - name[len + 2] = ']'; - name[len + 3] = '\0'; - GET_UNIFORM glUniform4fv(uniform->location, count, data); } diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 97e4c880644..d2384b9c065 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -209,6 +209,11 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material) return material->pass; } +GPUShader *GPU_material_get_shader(GPUMaterial *material) +{ + return material->pass ? GPU_pass_shader_get(material->pass) : NULL; +} + /* Return can be NULL if it's a world material. */ Material *GPU_material_get_material(GPUMaterial *material) { @@ -662,6 +667,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene, /* Caller must re-use materials. */ BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL); + /* HACK: Eevee assume this to create Ghash keys. */ + BLI_assert(sizeof(GPUPass) > 16); + /* allocate material */ GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); mat->ma = ma; diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index 876a6bef670..17d97dc05e2 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -34,6 +34,8 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "GPU_texture.h" + #include "gpu_material_library.h" #include "gpu_node_graph.h" @@ -298,13 +300,14 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, Image *ima, ImageUser *iuser, struct GPUTexture **colorband, - GPUNodeLinkType link_type) + GPUNodeLinkType link_type, + eGPUSamplerState sampler_state) { /* Find existing texture. */ int num_textures = 0; GPUMaterialTexture *tex = graph->textures.first; for (; tex; tex = tex->next) { - if (tex->ima == ima && tex->colorband == colorband) { + if (tex->ima == ima && tex->colorband == colorband && tex->sampler_state == sampler_state) { break; } num_textures++; @@ -316,6 +319,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, tex->ima = ima; tex->iuser = iuser; tex->colorband = colorband; + tex->sampler_state = sampler_state; BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures); if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) { BLI_snprintf( @@ -389,21 +393,29 @@ GPUNodeLink *GPU_uniform(const float *num) return link; } -GPUNodeLink *GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser) +GPUNodeLink *GPU_image(GPUMaterial *mat, + Image *ima, + ImageUser *iuser, + eGPUSamplerState sampler_state) { GPUNodeGraph *graph = gpu_material_node_graph(mat); GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE; - link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type); + link->texture = gpu_node_graph_add_texture( + graph, ima, iuser, NULL, link->link_type, sampler_state); return link; } -GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser) +GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, + Image *ima, + ImageUser *iuser, + eGPUSamplerState sampler_state) { GPUNodeGraph *graph = gpu_material_node_graph(mat); GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_TILED; - link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type); + link->texture = gpu_node_graph_add_texture( + graph, ima, iuser, NULL, link->link_type, sampler_state); return link; } @@ -412,7 +424,8 @@ GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iu GPUNodeGraph *graph = gpu_material_node_graph(mat); GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING; - link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type); + link->texture = gpu_node_graph_add_texture( + graph, ima, iuser, NULL, link->link_type, GPU_SAMPLER_MAX); return link; } @@ -424,7 +437,8 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro GPUNodeGraph *graph = gpu_material_node_graph(mat); GPUNodeLink *link = gpu_node_link_create(); link->link_type = GPU_NODE_LINK_COLORBAND; - link->texture = gpu_node_graph_add_texture(graph, NULL, NULL, colorband, link->link_type); + link->texture = gpu_node_graph_add_texture( + graph, NULL, NULL, colorband, link->link_type, GPU_SAMPLER_MAX); return link; } diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 8dfc992ae9f..66f98461047 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -331,6 +331,8 @@ GPUShader *GPU_shader_load_from_binary(const char *binary, glGetProgramiv(program, GL_LINK_STATUS, &success); if (success) { + glUseProgram(program); + GPUShader *shader = MEM_callocN(sizeof(*shader), __func__); shader->interface = GPU_shaderinterface_create(program); shader->program = program; @@ -572,6 +574,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, return NULL; } + glUseProgram(shader->program); shader->interface = GPU_shaderinterface_create(shader->program); return shader; @@ -726,13 +729,6 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name) { BLI_assert(shader && shader->program); const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name); - return uniform ? uniform->location : -2; -} - -int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name) -{ - BLI_assert(shader && shader->program); - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(shader->interface, name); return uniform ? uniform->location : -1; } @@ -750,6 +746,20 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) return ubo ? ubo->location : -1; } +int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name) +{ + BLI_assert(shader && shader->program); + const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name); + return ubo ? ubo->binding : -1; +} + +int GPU_shader_get_texture_binding(GPUShader *shader, const char *name) +{ + BLI_assert(shader && shader->program); + const GPUShaderInput *tex = GPU_shaderinterface_uniform(shader->interface, name); + return tex ? tex->binding : -1; +} + void *GPU_shader_get_interface(GPUShader *shader) { return shader->interface; @@ -837,34 +847,6 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value) glUniform1i(location, value); } -void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo) -{ - int bindpoint = GPU_uniformbuffer_bindpoint(ubo); - - if (location == -1) { - return; - } - - glUniformBlockBinding(shader->program, location, bindpoint); -} - -void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) -{ - int number = GPU_texture_bound_number(tex); - - if (number == -1) { - fprintf(stderr, "Texture is not bound.\n"); - BLI_assert(0); - return; - } - - if (location == -1) { - return; - } - - glUniform1i(location, number); -} - void GPU_shader_set_srgb_uniform(const GPUShaderInterface *interface) { const GPUShaderInput *srgb_uniform = GPU_shaderinterface_uniform_builtin( diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index 3218d12bc0d..84be8affc16 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -24,6 +24,9 @@ */ #include "BKE_global.h" + +#include "BLI_math_base.h" + #include "MEM_guardedalloc.h" #include "GPU_shader_interface.h" @@ -91,129 +94,136 @@ GPU_INLINE uint hash_string(const char *str) return i; } -GPU_INLINE void set_input_name(GPUShaderInterface *shaderface, - GPUShaderInput *input, - const char *name, - uint32_t name_len) +GPU_INLINE uint32_t set_input_name(GPUShaderInterface *shaderface, + GPUShaderInput *input, + char *name, + uint32_t name_len) { - input->name_offset = shaderface->name_buffer_offset; - input->name_hash = hash_string(name); - shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */ -} + /* remove "[0]" from array name */ + if (name[name_len - 1] == ']') { + name[name_len - 3] = '\0'; + name_len -= 3; + } -GPU_INLINE void shader_input_to_bucket(GPUShaderInput *input, - GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]) -{ - const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS; - input->next = buckets[bucket_index]; - buckets[bucket_index] = input; + input->name_offset = (uint32_t)(name - shaderface->name_buffer); + input->name_hash = hash_string(name); + return name_len + 1; /* include NULL terminator */ } -GPU_INLINE const GPUShaderInput *buckets_lookup( - GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS], - const char *name_buffer, - const char *name) +GPU_INLINE const GPUShaderInput *input_lookup(const GPUShaderInterface *shaderface, + const GPUShaderInput *const inputs, + const uint inputs_len, + const char *name) { const uint name_hash = hash_string(name); - const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS; - const GPUShaderInput *input = buckets[bucket_index]; - if (input == NULL) { - /* Requested uniform is not found at all. */ - return NULL; - } - /* Optimization bit: if there is no hash collision detected when constructing shader interface - * it means we can only request the single possible uniform. Surely, it's possible we request - * uniform which causes hash collision, but that will be detected in debug builds. */ - if (input->next == NULL) { - if (name_hash == input->name_hash) { -#if TRUST_NO_ONE - assert(match(name_buffer + input->name_offset, name)); -#endif - return input; - } - return NULL; - } - /* Work through possible collisions. */ - const GPUShaderInput *next = input; - while (next != NULL) { - input = next; - next = input->next; - if (input->name_hash != name_hash) { - continue; - } - if (match(name_buffer + input->name_offset, name)) { - return input; + /* Simple linear search for now. */ + for (int i = inputs_len - 1; i >= 0; i--) { + if (inputs[i].name_hash == name_hash) { + if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) { + /* Hash colision resolve. */ + for (; i >= 0 && inputs[i].name_hash == name_hash; i--) { + if (match(name, shaderface->name_buffer + inputs[i].name_offset)) { + return inputs + i; /* not found */ + } + } + return NULL; /* not found */ + } + else { + /* This is a bit dangerous since we could have a hash collision. + * where the asked uniform that does not exist has the same hash + * as a real uniform. */ + BLI_assert(match(name, shaderface->name_buffer + inputs[i].name_offset)); + return inputs + i; + } } } return NULL; /* not found */ } -GPU_INLINE void buckets_free(GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]) +/* Note that this modify the src array. */ +GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const uint input_len) { - for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; bucket_index++) { - GPUShaderInput *input = buckets[bucket_index]; - while (input != NULL) { - GPUShaderInput *input_next = input->next; - MEM_freeN(input); - input = input_next; + for (uint i = 0; i < input_len; i++) { + GPUShaderInput *input_src = &src[0]; + for (uint j = 1; j < input_len; j++) { + if (src[j].name_hash > input_src->name_hash) { + input_src = &src[j]; + } } + dst[i] = *input_src; + input_src->name_hash = 0; } } -static bool setup_builtin_uniform(GPUShaderInput *input, const char *name) +static int block_binding(int32_t program, uint32_t block_index) { - /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */ - - /* detect built-in uniforms (name must match) */ - for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) { - const char *builtin_name = BuiltinUniform_name(u); - if (match(name, builtin_name)) { - input->builtin_type = u; - return true; - } - } - input->builtin_type = GPU_UNIFORM_CUSTOM; - return false; + /* For now just assign a consecutive index. In the future, we should set it in + * the shader using layout(binding = i) and query its value. */ + glUniformBlockBinding(program, block_index, block_index); + return block_index; } -static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const char *name) +static int sampler_binding(int32_t program, + uint32_t uniform_index, + int32_t uniform_location, + int *sampler_len) { - GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif"); - - input->location = glGetUniformLocation(shaderface->program, name); - - const uint name_len = strlen(name); - /* Include NULL terminator. */ - shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, - shaderface->name_buffer_offset + name_len + 1); - char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset; - strcpy(name_buffer, name); - - set_input_name(shaderface, input, name, name_len); - setup_builtin_uniform(input, name); - - shader_input_to_bucket(input, shaderface->uniform_buckets); - if (input->builtin_type != GPU_UNIFORM_NONE && input->builtin_type != GPU_UNIFORM_CUSTOM) { - shaderface->builtin_uniforms[input->builtin_type] = input; + /* Identify sampler uniforms and asign sampler units to them. */ + GLint type; + glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type); + + switch (type) { + case GL_SAMPLER_1D: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: /* OpenGL 4.0 */ + case GL_SAMPLER_1D_SHADOW: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_1D_ARRAY: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_1D_ARRAY_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_2D_MULTISAMPLE: + case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_BUFFER: + case GL_INT_SAMPLER_1D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_1D_ARRAY: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D_MULTISAMPLE: + case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_INT_SAMPLER_BUFFER: + case GL_UNSIGNED_INT_SAMPLER_1D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: + case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_BUFFER: { + /* For now just assign a consecutive index. In the future, we should set it in + * the shader using layout(binding = i) and query its value. */ + int binding = *sampler_len; + glUniform1i(uniform_location, binding); + (*sampler_len)++; + return binding; + } + default: + return -1; } -#if DEBUG_SHADER_INTERFACE - printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n", - shaderface, - shaderface->program, - name, - input->location); -#endif - return input; } GPUShaderInterface *GPU_shaderinterface_create(int32_t program) { - GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface"); - shaderface->program = program; - -#if DEBUG_SHADER_INTERFACE - printf("%s {\n", __func__); /* enter function */ - printf("GPUShaderInterface %p, program %d\n", shaderface, program); +#ifndef NDEBUG + GLint curr_program; + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_program); + BLI_assert(curr_program == program); #endif GLint max_attr_name_len = 0, attr_len = 0; @@ -224,6 +234,11 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len); glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len); + GLint max_uniform_name_len = 0, active_uniform_len = 0, uniform_len = 0; + glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len); + glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_len); + uniform_len = active_uniform_len; + /* Work around driver bug with Intel HD 4600 on Windows 7/8, where * GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */ if (attr_len > 0 && max_attr_name_len == 0) { @@ -232,87 +247,185 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) if (ubo_len > 0 && max_ubo_name_len == 0) { max_ubo_name_len = 256; } + if (uniform_len > 0 && max_uniform_name_len == 0) { + max_uniform_name_len = 256; + } + + /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before + * allocating the uniform array. */ + GLint *uniforms_block_index = MEM_mallocN(sizeof(GLint) * active_uniform_len, __func__); + if (uniform_len > 0) { + GLuint *indices = MEM_mallocN(sizeof(GLuint) * active_uniform_len, __func__); + for (uint i = 0; i < uniform_len; i++) { + indices[i] = i; + } + + glGetActiveUniformsiv( + program, uniform_len, indices, GL_UNIFORM_BLOCK_INDEX, uniforms_block_index); + + MEM_freeN(indices); + + for (int i = 0; i < active_uniform_len; i++) { + /* If GL_UNIFORM_BLOCK_INDEX is not -1 it means the uniform belongs to a UBO. */ + if (uniforms_block_index[i] != -1) { + uniform_len--; + } + } + } + + uint32_t name_buffer_offset = 0; + const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len + + uniform_len * max_uniform_name_len; - const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len; + int input_tot_len = attr_len + ubo_len + uniform_len; + size_t interface_size = sizeof(GPUShaderInterface) + sizeof(GPUShaderInput) * input_tot_len; + + GPUShaderInterface *shaderface = MEM_callocN(interface_size, "GPUShaderInterface"); + shaderface->attribute_len = attr_len; + shaderface->ubo_len = ubo_len; + shaderface->uniform_len = uniform_len; shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer"); + GPUShaderInput *inputs = shaderface->inputs; + + /* Temp buffer. */ + int input_tmp_len = max_iii(attr_len, ubo_len, uniform_len); + GPUShaderInput *inputs_tmp = MEM_mallocN(sizeof(GPUShaderInput) * input_tmp_len, "name_buffer"); /* Attributes */ shaderface->enabled_attr_mask = 0; - for (uint32_t i = 0; i < attr_len; i++) { - GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr"); - GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; - char *name = shaderface->name_buffer + shaderface->name_buffer_offset; + for (int i = 0, idx = 0; i < attr_len; i++) { + char *name = shaderface->name_buffer + name_buffer_offset; + GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; GLsizei name_len = 0; + GLenum type; + GLint size; - glGetActiveAttrib( - program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name); - - /* remove "[0]" from array name */ - if (name[name_len - 1] == ']') { - name[name_len - 3] = '\0'; - name_len -= 3; - } - - /* TODO: reject DOUBLE gl_types */ - input->location = glGetAttribLocation(program, name); + glGetActiveAttrib(program, i, remaining_buffer, &name_len, &size, &type, name); + GLint location = glGetAttribLocation(program, name); /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ - if (input->location == -1) { - MEM_freeN(input); + if (location == -1) { + shaderface->attribute_len--; continue; } - if (input->location != -1) { - shaderface->enabled_attr_mask |= (1 << input->location); - } - - set_input_name(shaderface, input, name, name_len); - - shader_input_to_bucket(input, shaderface->attr_buckets); + GPUShaderInput *input = &inputs_tmp[idx++]; + input->location = input->binding = location; -#if DEBUG_SHADER_INTERFACE - printf("attr[%u] '%s' at location %d\n", i, name, input->location); -#endif + name_buffer_offset += set_input_name(shaderface, input, name, name_len); + shaderface->enabled_attr_mask |= (1 << input->location); } + sort_input_list(inputs, inputs_tmp, shaderface->attribute_len); + inputs += shaderface->attribute_len; + /* Uniform Blocks */ - for (uint32_t i = 0; i < ubo_len; i++) { - GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO"); - GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; - char *name = shaderface->name_buffer + shaderface->name_buffer_offset; + for (int i = 0, idx = 0; i < ubo_len; i++) { + char *name = shaderface->name_buffer + name_buffer_offset; + GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; GLsizei name_len = 0; glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name); - input->location = i; + GPUShaderInput *input = &inputs_tmp[idx++]; + input->binding = input->location = block_binding(program, i); - set_input_name(shaderface, input, name, name_len); + name_buffer_offset += set_input_name(shaderface, input, name, name_len); + shaderface->enabled_ubo_mask |= (1 << input->binding); + } + sort_input_list(inputs, inputs_tmp, shaderface->ubo_len); + inputs += shaderface->ubo_len; - shader_input_to_bucket(input, shaderface->ubo_buckets); + /* Uniforms */ + for (int i = 0, idx = 0, sampler = 0; i < active_uniform_len; i++) { + /* If GL_UNIFORM_BLOCK_INDEX is not -1 it means the uniform belongs to a UBO. */ + if (uniforms_block_index[i] != -1) { + continue; + } + char *name = shaderface->name_buffer + name_buffer_offset; + GLsizei remaining_buffer = name_buffer_len - name_buffer_offset; + GLsizei name_len = 0; -#if DEBUG_SHADER_INTERFACE - printf("ubo '%s' at location %d\n", name, input->location); -#endif + glGetActiveUniformName(program, i, remaining_buffer, &name_len, name); + + GPUShaderInput *input = &inputs_tmp[idx++]; + input->location = glGetUniformLocation(program, name); + input->binding = sampler_binding(program, i, input->location, &sampler); + + name_buffer_offset += set_input_name(shaderface, input, name, name_len); + shaderface->enabled_tex_mask |= (input->binding != -1) ? (1lu << input->binding) : 0lu; } + sort_input_list(inputs, inputs_tmp, shaderface->uniform_len); + /* Builtin Uniforms */ for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) { - const char *builtin_name = BuiltinUniform_name(u); - if (glGetUniformLocation(program, builtin_name) != -1) { - add_uniform((GPUShaderInterface *)shaderface, builtin_name); - } + shaderface->builtins[u].location = glGetUniformLocation(program, BuiltinUniform_name(u)); + shaderface->builtins[u].binding = -1; } + /* Batches ref buffer */ shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT; shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *), "GPUShaderInterface batches"); + MEM_freeN(uniforms_block_index); + MEM_freeN(inputs_tmp); + + /* Resize name buffer to save some memory. */ + if (name_buffer_offset < name_buffer_len) { + shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, name_buffer_offset); + } + +#if DEBUG_SHADER_INTERFACE + char *name_buf = shaderface->name_buffer; + printf("--- GPUShaderInterface %p, program %d ---\n", shaderface, program); + if (shaderface->attribute_len > 0) { + printf("Attributes {\n"); + for (int i = 0; i < shaderface->attribute_len; i++) { + GPUShaderInput *input = shaderface->inputs + i; + printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset); + } + printf("};\n"); + } + if (shaderface->ubo_len > 0) { + printf("Uniform Buffer Objects {\n"); + for (int i = 0; i < shaderface->ubo_len; i++) { + GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + i; + printf("\t(binding = %d) %s;\n", input->binding, name_buf + input->name_offset); + } + printf("};\n"); + } + if (shaderface->enabled_tex_mask > 0) { + printf("Samplers {\n"); + for (int i = 0; i < shaderface->uniform_len; i++) { + GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + + shaderface->ubo_len + i; + if (input->binding != -1) { + printf("\t(location = %d, binding = %d) %s;\n", + input->location, + input->binding, + name_buf + input->name_offset); + } + } + printf("};\n"); + } + if (shaderface->uniform_len > 0) { + printf("Uniforms {\n"); + for (int i = 0; i < shaderface->uniform_len; i++) { + GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + + shaderface->ubo_len + i; + if (input->binding == -1) { + printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset); + } + } + printf("};\n"); + } + printf("--- GPUShaderInterface end ---\n\n"); +#endif + return shaderface; } void GPU_shaderinterface_discard(GPUShaderInterface *shaderface) { - /* Free memory used by buckets and has entries. */ - buckets_free(shaderface->uniform_buckets); - buckets_free(shaderface->attr_buckets); - buckets_free(shaderface->ubo_buckets); /* Free memory used by name_buffer. */ MEM_freeN(shaderface->name_buffer); /* Remove this interface from all linked Batches vao cache. */ @@ -326,36 +439,25 @@ void GPU_shaderinterface_discard(GPUShaderInterface *shaderface) MEM_freeN(shaderface); } -const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface, - const char *name) +const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface, + const char *name) { - return buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name); + uint ofs = 0; + return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->attribute_len, name); } -const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *shaderface, - const char *name) +const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface, + const char *name) { - const GPUShaderInput *input = GPU_shaderinterface_uniform(shaderface, name); - /* If input is not found add it so it's found next time. */ - if (input == NULL) { - input = add_uniform((GPUShaderInterface *)shaderface, name); - - if ((G.debug & G_DEBUG_GPU) && (input->location == -1)) { - fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' not found!\n", name); - } - } + uint ofs = shaderface->attribute_len; + return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->ubo_len, name); +} -#if DEBUG_SHADER_UNIFORMS - if ((G.debug & G_DEBUG_GPU) && input->builtin_type != GPU_UNIFORM_NONE && - input->builtin_type != GPU_UNIFORM_CUSTOM) { - /* Warn if we find a matching builtin, since these can be looked up much quicker. */ - fprintf(stderr, - "GPUShaderInterface: Warning: Uniform '%s' is a builtin uniform but not queried as " - "such!\n", - name); - } -#endif - return (input->location != -1) ? input : NULL; +const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface, + const char *name) +{ + uint ofs = shaderface->attribute_len + shaderface->ubo_len; + return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->uniform_len, name); } const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface, @@ -366,19 +468,7 @@ const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterfa assert(builtin != GPU_UNIFORM_CUSTOM); assert(builtin != GPU_NUM_UNIFORMS); #endif - return shaderface->builtin_uniforms[builtin]; -} - -const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface, - const char *name) -{ - return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name); -} - -const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface, - const char *name) -{ - return buckets_lookup(shaderface->attr_buckets, shaderface->name_buffer, name); + return &shaderface->builtins[builtin]; } void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch) diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 38ba8bc612f..1d870ed2fdc 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -50,7 +50,9 @@ static struct GPUTextureGlobal { GPUTexture *invalid_tex_1D; GPUTexture *invalid_tex_2D; GPUTexture *invalid_tex_3D; -} GG = {NULL, NULL, NULL}; + /** Sampler objects used to replace internal texture parameters. */ + GLuint samplers[GPU_SAMPLER_MAX]; +} GG = {NULL}; /* Maximum number of FBOs a texture can be attached to. */ #define GPU_TEX_MAX_FBO_ATTACHED 12 @@ -72,7 +74,7 @@ typedef enum eGPUTextureFormatFlag { struct GPUTexture { int w, h, d; /* width/height/depth */ int orig_w, orig_h; /* width/height (of source data), optional. */ - int number; /* number for multitexture binding */ + int number; /* Texture unit to which this texture is bound. */ int refcount; /* reference count */ GLenum target; /* GL_TEXTURE_* */ GLenum target_base; /* same as target, (but no multisample) @@ -81,6 +83,7 @@ struct GPUTexture { eGPUTextureFormat format; eGPUTextureFormatFlag format_flag; + eGPUSamplerState sampler_state; /* Internal Sampler state. */ int mipmaps; /* number of mipmaps */ int components; /* number of color/alpha channels */ @@ -827,12 +830,12 @@ GPUTexture *GPU_texture_create_nD(int w, tex->h = h; tex->d = d; tex->samples = samples; - tex->number = -1; tex->refcount = 1; tex->format = tex_format; tex->components = gpu_get_component_count(tex_format); tex->mipmaps = 0; tex->format_flag = 0; + tex->number = -1; if (n == 2) { if (d == 0) { @@ -976,26 +979,13 @@ GPUTexture *GPU_texture_create_nD(int w, if (GPU_texture_stencil(tex) || /* Does not support filtering */ GPU_texture_integer(tex) || /* Does not support filtering */ GPU_texture_depth(tex)) { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER; } else { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (GPU_texture_depth(tex)) { - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - } - - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - if (n > 1) { - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - if (n > 2) { - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + tex->sampler_state = GPU_SAMPLER_DEFAULT; } + /* Avoid issue with incomplete textures. */ + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindTexture(tex->target, 0); @@ -1014,12 +1004,12 @@ GPUTexture *GPU_texture_cube_create(int w, tex->h = w; tex->d = d; tex->samples = 0; - tex->number = -1; tex->refcount = 1; tex->format = tex_format; tex->components = gpu_get_component_count(tex_format); tex->mipmaps = 0; tex->format_flag = GPU_FORMAT_CUBE; + tex->number = -1; if (d == 0) { tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP; @@ -1117,22 +1107,13 @@ GPUTexture *GPU_texture_cube_create(int w, if (GPU_texture_stencil(tex) || /* Does not support filtering */ GPU_texture_integer(tex) || /* Does not support filtering */ GPU_texture_depth(tex)) { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER; } else { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + tex->sampler_state = GPU_SAMPLER_DEFAULT; } - - if (GPU_texture_depth(tex)) { - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - } - - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + /* Avoid issue with incomplete textures. */ + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindTexture(tex->target, 0); @@ -1143,13 +1124,13 @@ GPUTexture *GPU_texture_cube_create(int w, GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint buffer) { GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->number = -1; tex->refcount = 1; tex->format = tex_format; tex->components = gpu_get_component_count(tex_format); tex->format_flag = 0; tex->target_base = tex->target = GL_TEXTURE_BUFFER; tex->mipmaps = 0; + tex->number = -1; GLenum internalformat = gpu_format_to_gl_internalformat(tex_format); @@ -1196,11 +1177,15 @@ GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode) { GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->bindcode = bindcode; - tex->number = -1; tex->refcount = 1; tex->target = textarget; tex->target_base = textarget; tex->samples = 0; + tex->sampler_state = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO; + if (GPU_get_mipmap()) { + tex->sampler_state |= (GPU_SAMPLER_MIPMAP | GPU_SAMPLER_FILTER); + } + tex->number = -1; if (!glIsTexture(tex->bindcode)) { GPU_print_error_debug("Blender Texture Not Loaded"); @@ -1727,16 +1712,17 @@ void GPU_invalid_tex_free(void) } } -void GPU_texture_bind(GPUTexture *tex, int number) +/* set_number is to save the the texture unit for setting texture parameters. */ +void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number) { - BLI_assert(number >= 0); + BLI_assert(unit >= 0); - if (number >= GPU_max_textures()) { + if (unit >= GPU_max_textures()) { fprintf(stderr, "Not enough texture slots.\n"); return; } - if ((G.debug & G_DEBUG)) { + if (G.debug & G_DEBUG) { for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; i++) { if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) { fprintf(stderr, @@ -1748,16 +1734,27 @@ void GPU_texture_bind(GPUTexture *tex, int number) } } - glActiveTexture(GL_TEXTURE0 + number); + if (set_number) { + tex->number = unit; + } + + glActiveTexture(GL_TEXTURE0 + unit); + + state = (state < GPU_SAMPLER_MAX) ? state : tex->sampler_state; if (tex->bindcode != 0) { glBindTexture(tex->target, tex->bindcode); + glBindSampler(unit, GG.samplers[state]); } else { GPU_invalid_tex_bind(tex->target_base); + glBindSampler(unit, 0); } +} - tex->number = number; +void GPU_texture_bind(GPUTexture *tex, int unit) +{ + GPU_texture_bind_ex(tex, GPU_SAMPLER_MAX, unit, true); } void GPU_texture_unbind(GPUTexture *tex) @@ -1768,13 +1765,26 @@ void GPU_texture_unbind(GPUTexture *tex) glActiveTexture(GL_TEXTURE0 + tex->number); glBindTexture(tex->target, 0); - + glBindSampler(tex->number, 0); tex->number = -1; } -int GPU_texture_bound_number(GPUTexture *tex) +void GPU_texture_unbind_all(void) { - return tex->number; + for (int i = 0; i < GPU_max_textures(); i++) { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D_ARRAY, 0); + glBindTexture(GL_TEXTURE_1D, 0); + glBindTexture(GL_TEXTURE_1D_ARRAY, 0); + glBindTexture(GL_TEXTURE_3D, 0); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + glBindTexture(GL_TEXTURE_BUFFER, 0); + if (GPU_arb_texture_cube_map_array_is_supported()) { + glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY_ARB, 0); + } + glBindSampler(i, 0); + } } #define WARN_NOT_BOUND(_tex) \ @@ -1798,8 +1808,8 @@ void GPU_texture_generate_mipmap(GPUTexture *tex) if (GPU_texture_depth(tex)) { /* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789). - * In this case we just create a complete texture with mipmaps manually without down-sampling. - * You must initialize the texture levels using other methods like + * In this case we just create a complete texture with mipmaps manually without + * down-sampling. You must initialize the texture levels using other methods like * GPU_framebuffer_recursive_downsample(). */ eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format); for (int i = 1; i < levels; i++) { @@ -1905,69 +1915,35 @@ void GPU_texture_copy(GPUTexture *dst, GPUTexture *src) void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare) { - WARN_NOT_BOUND(tex); - /* Could become an assertion ? (fclem) */ if (!GPU_texture_depth(tex)) { return; } - - GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE; - - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode); + SET_FLAG_FROM_TEST(tex->sampler_state, use_compare, GPU_SAMPLER_COMPARE); } void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter) { - WARN_NOT_BOUND(tex); - /* Stencil and integer format does not support filtering. */ BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); - GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST; - - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter); + SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER); } void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter) { - WARN_NOT_BOUND(tex); - /* Stencil and integer format does not support filtering. */ - BLI_assert((!use_filter && !use_mipmap) || + BLI_assert(!(use_filter || use_mipmap) || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); - GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST; - GLenum mipmap = ((use_filter) ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR : - (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST); - - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter); + SET_FLAG_FROM_TEST(tex->sampler_state, use_mipmap, GPU_SAMPLER_MIPMAP); + SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER); } void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp) { - WARN_NOT_BOUND(tex); - - GLenum repeat = (use_repeat) ? GL_REPEAT : (use_clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER; - - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat); - if (tex->target_base != GL_TEXTURE_1D) { - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat); - } - if (tex->target_base == GL_TEXTURE_3D) { - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat); - } - - if (repeat == GL_CLAMP_TO_BORDER) { - const float black[] = {0.0f, 0.0f, 0.0f, 0.0f}; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, black); - } + SET_FLAG_FROM_TEST(tex->sampler_state, use_repeat, GPU_SAMPLER_REPEAT); + SET_FLAG_FROM_TEST(tex->sampler_state, !use_clamp, GPU_SAMPLER_CLAMP_BORDER); } void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels) @@ -1981,34 +1957,6 @@ void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels) glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, (channels >= 4) ? GL_ALPHA : GL_ONE); } -static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter) -{ - switch (filter) { - case GPU_NEAREST: - return GL_NEAREST; - case GPU_LINEAR: - return GL_LINEAR; - default: - BLI_assert(!"Unhandled filter mode"); - return GL_NEAREST; - } -} - -void GPU_texture_filters(GPUTexture *tex, - eGPUFilterFunction min_filter, - eGPUFilterFunction mag_filter) -{ - WARN_NOT_BOUND(tex); - - /* Stencil and integer format does not support filtering. */ - BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); - BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR); - - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter)); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter)); -} - void GPU_texture_free(GPUTexture *tex) { tex->refcount--; @@ -2169,3 +2117,55 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size) size[2] = max_ii(1, tex->d / div); } } + +/* -------------------------------------------------------------------- */ +/** \name GPU Sampler Objects + * + * Simple wrapper around opengl sampler objects. + * Override texture sampler state for one sampler unit only. + * \{ */ + +void GPU_samplers_init(void) +{ + glGenSamplers(GPU_SAMPLER_MAX, GG.samplers); + for (int i = 0; i < GPU_SAMPLER_MAX; i++) { + eGPUSamplerState state = i; + GLenum clamp_type = (state & GPU_SAMPLER_CLAMP_BORDER) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE; + GLenum wrap_s = (state & GPU_SAMPLER_REPEAT_S) ? GL_REPEAT : clamp_type; + GLenum wrap_t = (state & GPU_SAMPLER_REPEAT_T) ? GL_REPEAT : clamp_type; + GLenum wrap_r = (state & GPU_SAMPLER_REPEAT_R) ? GL_REPEAT : clamp_type; + GLenum mag_filter = (state & GPU_SAMPLER_FILTER) ? GL_LINEAR : GL_NEAREST; + GLenum min_filter = (state & GPU_SAMPLER_FILTER) ? + ((state & GPU_SAMPLER_MIPMAP) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) : + ((state & GPU_SAMPLER_MIPMAP) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST); + GLenum compare_mode = (state & GPU_SAMPLER_COMPARE) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE; + float aniso_filter = ((state & GPU_SAMPLER_MIPMAP) && (state & GPU_SAMPLER_ANISO)) ? + GPU_get_anisotropic() : + 1.0f; + + glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_S, wrap_s); + glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_T, wrap_t); + glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_R, wrap_r); + glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MIN_FILTER, min_filter); + glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MAG_FILTER, mag_filter); + glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_MODE, compare_mode); + glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + if (GLEW_EXT_texture_filter_anisotropic) { + glSamplerParameterf(GG.samplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso_filter); + } + + /** Other states are left to default: + * - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}. + * - GL_TEXTURE_MIN_LOD is -1000. + * - GL_TEXTURE_MAX_LOD is 1000. + * - GL_TEXTURE_LOD_BIAS is 0.0f. + **/ + } +} + +void GPU_samplers_free(void) +{ + glDeleteSamplers(GPU_SAMPLER_MAX, GG.samplers); +} + +/** \} */ diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c index e6a9cb8f2f2..b84a7e0f554 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.c +++ b/source/blender/gpu/intern/gpu_vertex_format.c @@ -23,8 +23,6 @@ * GPU vertex format */ -#include "GPU_shader_interface.h" - #include "GPU_vertex_format.h" #include "gpu_vertex_format_private.h" #include <stddef.h> @@ -34,6 +32,9 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "GPU_shader.h" +#include "gpu_shader_private.h" + #define PACK_DEBUG 0 #if PACK_DEBUG @@ -391,38 +392,37 @@ void VertexFormat_pack(GPUVertFormat *format) format->packed = true; } -static uint calc_input_component_size(const GPUShaderInput *input) +static uint calc_component_size(const GLenum gl_type) { - int size = input->size; - switch (input->gl_type) { + switch (gl_type) { case GL_FLOAT_VEC2: case GL_INT_VEC2: case GL_UNSIGNED_INT_VEC2: - return size * 2; + return 2; case GL_FLOAT_VEC3: case GL_INT_VEC3: case GL_UNSIGNED_INT_VEC3: - return size * 3; + return 3; case GL_FLOAT_VEC4: case GL_FLOAT_MAT2: case GL_INT_VEC4: case GL_UNSIGNED_INT_VEC4: - return size * 4; + return 4; case GL_FLOAT_MAT3: - return size * 9; + return 9; case GL_FLOAT_MAT4: - return size * 16; + return 16; case GL_FLOAT_MAT2x3: case GL_FLOAT_MAT3x2: - return size * 6; + return 6; case GL_FLOAT_MAT2x4: case GL_FLOAT_MAT4x2: - return size * 8; + return 8; case GL_FLOAT_MAT3x4: case GL_FLOAT_MAT4x3: - return size * 12; + return 12; default: - return size; + return 1; } } @@ -466,42 +466,39 @@ static void get_fetch_mode_and_comp_type(int gl_type, } } -void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterface *shaderface) +void GPU_vertformat_from_shader(GPUVertFormat *format, const GPUShader *shader) { - const char *name_buffer = shaderface->name_buffer; - - for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) { - const GPUShaderInput *input = shaderface->attr_buckets[i]; - if (input == NULL) { - continue; - } + GPU_vertformat_clear(format); + GPUVertAttr *attr = &format->attrs[0]; - const GPUShaderInput *next = input; - while (next != NULL) { - input = next; - next = input->next; + GLint attr_len; + glGetProgramiv(shader->program, GL_ACTIVE_ATTRIBUTES, &attr_len); - /* OpenGL attributes such as `gl_VertexID` have a location of -1. */ - if (input->location < 0) { - continue; - } - - format->name_len++; /* multiname support */ - format->attr_len++; - - GPUVertCompType comp_type; - GPUVertFetchMode fetch_mode; - get_fetch_mode_and_comp_type(input->gl_type, &comp_type, &fetch_mode); + for (int i = 0; i < attr_len; i++) { + char name[256]; + GLenum gl_type; + GLint size; + glGetActiveAttrib(shader->program, i, sizeof(name), NULL, &size, &gl_type, name); - GPUVertAttr *attr = &format->attrs[input->location]; - - attr->names[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset); - attr->offset = 0; /* offsets & stride are calculated later (during pack) */ - attr->comp_len = calc_input_component_size(input); - attr->sz = attr->comp_len * 4; - attr->fetch_mode = fetch_mode; - attr->comp_type = comp_type; - attr->gl_comp_type = convert_comp_type_to_gl(comp_type); + /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ + if (glGetAttribLocation(shader->program, name) == -1) { + continue; } + + format->name_len++; /* multiname support */ + format->attr_len++; + + GPUVertCompType comp_type; + GPUVertFetchMode fetch_mode; + get_fetch_mode_and_comp_type(gl_type, &comp_type, &fetch_mode); + + attr->names[attr->name_len++] = copy_attr_name(format, name); + attr->offset = 0; /* offsets & stride are calculated later (during pack) */ + attr->comp_len = calc_component_size(gl_type) * size; + attr->sz = attr->comp_len * 4; + attr->fetch_mode = fetch_mode; + attr->comp_type = comp_type; + attr->gl_comp_type = convert_comp_type_to_gl(comp_type); + attr += 1; } } diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index f30270b9eed..753da8544ea 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -382,12 +382,10 @@ GPUTexture *GPU_viewport_texture_pool_query( } tex = GPU_texture_create_2d(width, height, format, NULL, NULL); - GPU_texture_bind(tex, 0); /* Doing filtering for depth does not make sense when not doing shadow mapping, * and enabling texture filtering on integer texture make them unreadable. */ bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex); GPU_texture_filter_mode(tex, do_filter); - GPU_texture_unbind(tex); ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture"); tmp_tex->texture = tex; diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl index 62f76d46088..4cb00c15b78 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl @@ -1,8 +1,16 @@ -void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result) +void node_output_material( + Closure surface, Closure volume, vec3 displacement, float alpha_threshold, out Closure result) { #ifdef VOLUMETRICS result = volume; #else result = surface; +# if defined(USE_ALPHA_HASH) + /* Alpha clip emulation. */ + if (alpha_threshold >= 0.0) { + float alpha = saturate(1.0 - avg(result.transmittance)); + result.transmittance = vec3(step(alpha, alpha_threshold)); + } +# endif #endif } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl index 9bd36f8a757..20a65f23c05 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl @@ -15,16 +15,11 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) #endif } -void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv) +void node_tex_environment_equirectangular(vec3 co, out vec3 uv) { vec3 nco = normalize(co); uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; - - /* Fix pole bleeding */ - float half_height = clamp_size / float(textureSize(ima, 0).y); - uv.y = clamp(uv.y, half_height, 1.0 - half_height); - uv.z = 0.0; } void node_tex_environment_mirror_ball(vec3 co, out vec3 uv) diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl index c39bec8ac64..df949f7358b 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl @@ -54,19 +54,6 @@ void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alp alpha = color.a; } -void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - color = safe_color(textureLod(ima, co.xy, 0.0)); - alpha = color.a; -} - -void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy); - color = safe_color(texelFetch(ima, pix, 0)); - alpha = color.a; -} - /** \param f: Signed distance to texel center. */ void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3) { @@ -79,8 +66,7 @@ void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w2 = 1.0 - w0 - w1 - w3; } -void node_tex_image_cubic_ex( - vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha) +void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha) { vec2 tex_size = vec2(textureSize(ima, 0).xy); @@ -101,9 +87,6 @@ void node_tex_image_cubic_ex( final_co.xy = tc - 1.0 + f0; final_co.zw = tc + 1.0 + f1; - if (do_extend == 1.0) { - final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5); - } final_co /= tex_size.xyxy; color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y; @@ -136,22 +119,6 @@ void node_tex_image_cubic_ex( alpha = color.a; } -void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); -} - -void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - node_tex_image_cubic_ex(co, ima, 1.0, color, alpha); -} - -void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha) -{ - /* use cubic for now */ - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); -} - void tex_box_sample_linear( vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) { @@ -175,32 +142,6 @@ void tex_box_sample_linear( color3 = texture(ima, uv); } -void tex_box_sample_nearest( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - ivec2 pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy); - color1 = texelFetch(ima, pix, 0); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy); - color2 = texelFetch(ima, pix, 0); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy); - color3 = texelFetch(ima, pix, 0); -} - void tex_box_sample_cubic( vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) { @@ -210,36 +151,23 @@ void tex_box_sample_cubic( if (N.x < 0.0) { uv.x = 1.0 - uv.x; } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha); + node_tex_image_cubic(uv.xyy, ima, color1, alpha); /* Y projection */ uv = texco.xz; if (N.y > 0.0) { uv.x = 1.0 - uv.x; } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha); + node_tex_image_cubic(uv.xyy, ima, color2, alpha); /* Z projection */ uv = texco.yx; if (N.z > 0.0) { uv.x = 1.0 - uv.x; } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha); + node_tex_image_cubic(uv.xyy, ima, color3, alpha); } -void tex_box_sample_smart( - vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) -{ - tex_box_sample_cubic(texco, N, ima, color1, color2, color3); -} - -void node_tex_image_box(vec3 texco, - vec3 N, - vec4 color1, - vec4 color2, - vec4 color3, - sampler2D ima, - float blend, - out vec4 color, - out float alpha) +void tex_box_blend( + vec3 N, vec4 color1, vec4 color2, vec4 color3, float blend, out vec4 color, out float alpha) { /* project from direction vector to barycentric coordinates in triangles */ N = abs(N); @@ -284,70 +212,6 @@ void node_tex_image_box(vec3 texco, alpha = color.a; } -void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - vec2 minco = min(co.xy, 1.0 - co.xy); - minco = clamp(minco * tex_size + 0.5, 0.0, 1.0); - float fac = minco.x * minco.y; - - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; -} - -void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec4 minco = vec4(co.xy, 1.0 - co.xy); - color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor; - alpha = color.a; -} - -void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - vec2 tex_size = vec2(textureSize(ima, 0).xy); - - co.xy *= tex_size; - /* texel center */ - vec2 tc = floor(co.xy - 0.5) + 0.5; - vec2 w0, w1, w2, w3; - cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); - - /* TODO Optimize this part. I'm sure there is a smarter way to do that. - * Could do that when sampling? */ -#define CLIP_CUBIC_SAMPLE(samp, size) \ - (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size)))) - ivec2 itex_size = textureSize(ima, 0).xy; - float fac; - fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y; -#undef CLIP_CUBIC_SAMPLE - - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; -} - -void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) -{ - tex_clip_cubic(co, ima, icolor, color, alpha); -} - void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) { color = vec4(0.0); @@ -389,20 +253,6 @@ void node_tex_tile_linear( alpha = color.a; } -void node_tex_tile_nearest( - vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha) -{ - if (node_tex_tile_lookup(co, ima, map)) { - ivec3 pix = ivec3(fract(co.xy) * textureSize(ima, 0).xy, co.z); - color = safe_color(texelFetch(ima, pix, 0)); - } - else { - color = vec4(1.0, 0.0, 1.0, 1.0); - } - - alpha = color.a; -} - void node_tex_tile_cubic( vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha) { @@ -437,9 +287,3 @@ void node_tex_tile_cubic( alpha = color.a; } - -void node_tex_tile_smart( - vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha) -{ - node_tex_tile_cubic(co, ima, map, color, alpha); -} diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index a747ed3be11..8c9c1ba8b32 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -339,6 +339,7 @@ typedef enum eBrushPoseDeformType { typedef enum eBrushPoseOriginType { BRUSH_POSE_ORIGIN_TOPOLOGY = 0, BRUSH_POSE_ORIGIN_FACE_SETS = 1, + BRUSH_POSE_ORIGIN_FACE_SETS_FK = 2, } eBrushPoseOriginType; /* Gpencilsettings.Vertex_mode */ diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 029352f3d85..acc020ec710 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -33,6 +33,7 @@ extern "C" { #endif struct AnimData; +struct BVHCache; struct Ipo; struct Key; struct LinkNode; @@ -99,8 +100,8 @@ typedef struct Mesh_Runtime { struct MLoopTri_Store looptris; - /** 'BVHCache', for 'BKE_bvhutil.c' */ - struct LinkNode *bvh_cache; + /** `BVHCache` defined in 'BKE_bvhutil.c' */ + struct BVHCache *bvh_cache; /** Non-manifold boundary data for Shrinkwrap Target Project. */ struct ShrinkwrapBoundaryData *shrinkwrap_data; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 18cd3872d1f..37d0d25227e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -906,8 +906,6 @@ typedef struct ImagePaintSettings { /** Mode used for texture painting. */ int mode; - /** Wm handle. */ - void *paintcursor; /** Workaround until we support true layer masks. */ struct Image *stencil; /** Clone layer for image mode for projective texture painting. */ diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index 7a7ab1085dd..1bcf7f434f2 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -50,6 +50,7 @@ void RNA_free(BlenderRNA *brna); void RNA_define_verify_sdna(bool verify); void RNA_define_animate_sdna(bool animate); void RNA_define_fallback_property_update(int noteflag, const char *updatefunc); +void RNA_define_lib_overridable(const bool make_overridable); void RNA_init(void); void RNA_exit(void); diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 85bd17c737e..f87e8824bc2 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -637,7 +637,7 @@ static char *rna_def_property_get_func( if (!manualfunc) { if (!dp->dnastructname || !dp->dnaname) { CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } @@ -654,7 +654,7 @@ static char *rna_def_property_get_func( prop->identifier, dp->dnatype, RNA_property_typename(prop->type)); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } } @@ -667,7 +667,7 @@ static char *rna_def_property_get_func( prop->identifier, dp->dnatype, RNA_property_typename(prop->type)); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } } @@ -679,7 +679,7 @@ static char *rna_def_property_get_func( prop->identifier, dp->dnatype, RNA_property_typename(prop->type)); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } } @@ -1020,7 +1020,7 @@ static char *rna_def_property_set_func( if (!dp->dnastructname || !dp->dnaname) { if (prop->flag & PROP_EDITABLE) { CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } return NULL; } @@ -1263,7 +1263,7 @@ static char *rna_def_property_length_func( if (!manualfunc) { if (!dp->dnastructname || !dp->dnaname) { CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } } @@ -1289,7 +1289,7 @@ static char *rna_def_property_length_func( if (prop->type == PROP_COLLECTION && (!(dp->dnalengthname || dp->dnalengthfixed) || !dp->dnaname)) { CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } } @@ -1338,7 +1338,7 @@ static char *rna_def_property_begin_func( if (!manualfunc) { if (!dp->dnastructname || !dp->dnaname) { CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } } @@ -1848,7 +1848,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) if (!pprop->type) { CLOG_ERROR( &LOG, "%s.%s, pointer must have a struct type.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } break; } @@ -1896,21 +1896,21 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) "%s.%s, collection must have a begin function.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } if (!cprop->next) { CLOG_ERROR(&LOG, "%s.%s, collection must have a next function.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } if (!cprop->get) { CLOG_ERROR(&LOG, "%s.%s, collection must have a get function.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } } if (!cprop->item_type) { @@ -1918,7 +1918,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp) "%s.%s, collection must have a struct type.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } break; } @@ -3656,7 +3656,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr errnest, prop->identifier, eprop->defaultvalue & ~totflag); - DefRNA.error = 1; + DefRNA.error = true; } } else { @@ -3666,7 +3666,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr srna->identifier, errnest, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } } } @@ -3676,7 +3676,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr srna->identifier, errnest, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } break; } @@ -4218,7 +4218,7 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE if (srna->reg && !srna->refine) { CLOG_ERROR( &LOG, "%s has a register function, must also have refine function.", srna->identifier); - DefRNA.error = 1; + DefRNA.error = true; } func = srna->functions.first; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 9e78eec9c25..209e5a1ff8b 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1978,6 +1978,11 @@ static void rna_def_brush(BlenderRNA *brna) 0, "Face Sets", "Creates a pose segment per face sets, starting from the active face set"}, + {BRUSH_POSE_ORIGIN_FACE_SETS_FK, + "FACE_SETS_FK", + 0, + "Face Sets FK", + "Simulates an FK deformation using the Face Set under the cursor as control"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 47a09233769..79ee9619e36 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -193,6 +193,8 @@ static void rna_def_camera_background_image(BlenderRNA *brna) RNA_def_struct_ui_text( srna, "Background Image", "Image and settings for display in the 3D View background"); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "source"); RNA_def_property_enum_items(prop, bgpic_source_items); @@ -301,6 +303,8 @@ static void rna_def_camera_background_image(BlenderRNA *brna) RNA_def_property_enum_items(prop, bgpic_camera_frame_items); RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + RNA_define_lib_overridable(false); } static void rna_def_camera_background_images(BlenderRNA *brna, PropertyRNA *cprop) @@ -356,6 +360,8 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna) RNA_def_struct_nested(brna, srna, "Camera"); RNA_def_struct_ui_text(srna, "Stereo", "Stereoscopy settings for a Camera data-block"); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "convergence_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, convergence_mode_items); RNA_def_property_ui_text(prop, "Mode", ""); @@ -409,6 +415,8 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Pole Merge End Angle", "Angle at which interocular distance is 0"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); + + RNA_define_lib_overridable(false); } static void rna_def_camera_dof_settings_data(BlenderRNA *brna) @@ -421,6 +429,8 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_CameraDOFSettings_path"); RNA_def_struct_ui_text(srna, "Depth of Field", "Depth of Field settings"); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_DOF_ENABLED); RNA_def_property_ui_text(prop, "Depth of Field", "Use Depth of Field"); @@ -469,6 +479,8 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna) RNA_def_property_range(prop, 0.01f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update"); + + RNA_define_lib_overridable(false); } void RNA_def_camera(BlenderRNA *brna) @@ -505,6 +517,8 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Camera", "Camera data-block for storing camera settings"); RNA_def_struct_ui_icon(srna, ICON_CAMERA_DATA); + RNA_define_lib_overridable(true); + /* Enums */ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_type_items); @@ -736,6 +750,8 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Background Images", "List of background images"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + RNA_define_lib_overridable(false); + rna_def_animdata_common(srna); rna_def_camera_background_image(brna); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index dc0cde953f4..07ad8cbb37d 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -824,6 +824,8 @@ static void rna_def_constraint_headtail_common(StructRNA *srna) { PropertyRNA *prop; + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, "bConstraint", "headtail"); RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1"); @@ -835,12 +837,16 @@ static void rna_def_constraint_headtail_common(StructRNA *srna) "Follow B-Bone", "Follow shape of B-Bone segments when calculating Head/Tail position"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_target_common(StructRNA *srna) { PropertyRNA *prop; + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); RNA_def_property_ui_text(prop, "Target", "Target object"); @@ -852,6 +858,8 @@ static void rna_def_constraint_target_common(StructRNA *srna) RNA_def_property_string_sdna(prop, NULL, "subtarget"); RNA_def_property_ui_text(prop, "Sub-Target", "Armature bone, mesh or lattice vertex group, ..."); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constrainttarget(BlenderRNA *brna) @@ -864,6 +872,8 @@ static void rna_def_constrainttarget(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_ConstraintTarget_path"); RNA_def_struct_sdna(srna, "bConstraintTarget"); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); RNA_def_property_ui_text(prop, "Target", "Target object"); @@ -879,6 +889,8 @@ static void rna_def_constrainttarget(BlenderRNA *brna) prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_dependency_update"); /* space, flag and type still to do */ + + RNA_define_lib_overridable(false); } static void rna_def_constrainttarget_bone(BlenderRNA *brna) @@ -892,6 +904,8 @@ static void rna_def_constrainttarget_bone(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_ConstraintTarget_path"); RNA_def_struct_sdna(srna, "bConstraintTarget"); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); RNA_def_property_ui_text(prop, "Target", "Target armature"); @@ -913,6 +927,8 @@ static void rna_def_constrainttarget_bone(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Blend Weight", "Blending weight of this bone"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_childof(BlenderRNA *brna) @@ -928,6 +944,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_location_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CHILDOF_LOCX); RNA_def_property_ui_text(prop, "Location X", "Use X Location of Parent"); @@ -985,6 +1003,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_python(BlenderRNA *brna) @@ -996,6 +1016,8 @@ static void rna_def_constraint_python(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Python Constraint", "Use Python script for constraint evaluation"); RNA_def_struct_sdna_from(srna, "bPythonConstraint", "data"); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "targets", NULL); RNA_def_property_struct_type(prop, "ConstraintTarget"); @@ -1021,6 +1043,8 @@ static void rna_def_constraint_python(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", PYCON_SCRIPTERROR); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Script Error", "The linked Python script has thrown an error"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_armature_deform_targets(BlenderRNA *brna, PropertyRNA *cprop) @@ -1065,6 +1089,8 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bArmatureConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_ARMATURE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "targets", NULL); RNA_def_property_struct_type(prop, "ConstraintTargetBone"); @@ -1095,6 +1121,8 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna) "Use the current bone location for envelopes and choosing B-Bone " "segments instead of rest position"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_kinematic(BlenderRNA *brna) @@ -1121,6 +1149,8 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 0, 10000); RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations"); @@ -1240,6 +1270,8 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 100.f); RNA_def_property_ui_text(prop, "Distance", "Radius of limiting sphere"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_track_to(BlenderRNA *brna) @@ -1266,6 +1298,8 @@ static void rna_def_constraint_track_to(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_CON_TRACKTO); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "reserved1"); RNA_def_property_enum_items(prop, track_axis_items); @@ -1283,6 +1317,8 @@ static void rna_def_constraint_track_to(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Target Z", "Target's Z axis, not World Z axis, will constraint the Up direction"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_locate_like(BlenderRNA *brna) @@ -1300,6 +1336,8 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_X); RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X location"); @@ -1334,6 +1372,8 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_OFFSET); RNA_def_property_ui_text(prop, "Offset", "Add original location into copied location"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_rotate_like(BlenderRNA *brna) @@ -1370,6 +1410,8 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", ROTLIKE_X); RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X rotation"); @@ -1420,6 +1462,8 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Offset", "DEPRECATED: Add original rotation into copied rotation"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_size_like(BlenderRNA *brna) @@ -1434,6 +1478,8 @@ static void rna_def_constraint_size_like(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_X); RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X scale"); @@ -1476,6 +1522,8 @@ static void rna_def_constraint_size_like(BlenderRNA *brna) "Additive", "Use addition instead of multiplication to combine scale (2.7 compatibility)"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_same_volume(BlenderRNA *brna) @@ -1518,6 +1566,8 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bSameVolumeConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_SAMEVOL); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "free_axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "free_axis"); RNA_def_property_enum_items(prop, axis_items); @@ -1535,6 +1585,8 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna) RNA_def_property_range(prop, 0.001f, 100.0f); RNA_def_property_ui_text(prop, "Volume", "Volume of the bone at rest"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_transform_like(BlenderRNA *brna) @@ -1575,12 +1627,16 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mix_mode"); RNA_def_property_enum_items(prop, mix_mode_items); RNA_def_property_ui_text( prop, "Mix Mode", "Specify how the copied and existing transformations are combined"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_minmax(BlenderRNA *brna) @@ -1606,6 +1662,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "floor_location", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "minmaxflag"); RNA_def_property_enum_items(prop, minmax_items); @@ -1622,6 +1680,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna) RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, -1); RNA_def_property_ui_text(prop, "Offset", "Offset of floor from object origin"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_action(BlenderRNA *brna) @@ -1673,6 +1733,8 @@ static void rna_def_constraint_action(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mix_mode"); RNA_def_property_enum_items(prop, mix_mode_items); @@ -1733,6 +1795,8 @@ static void rna_def_constraint_action(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Minimum", "Minimum value for target channel range"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_ActionConstraint_minmax_range"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_locked_track(BlenderRNA *brna) @@ -1760,6 +1824,8 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "trackflag"); RNA_def_property_enum_items(prop, track_axis_items); @@ -1771,6 +1837,8 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna) RNA_def_property_enum_items(prop, lock_items); RNA_def_property_ui_text(prop, "Locked Axis", "Axis that points upward"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_follow_path(BlenderRNA *brna) @@ -1800,6 +1868,8 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bFollowPathConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_FOLLOWPATH); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll"); @@ -1852,6 +1922,8 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_RADIUS); RNA_def_property_ui_text(prop, "Curve Radius", "Object is scaled by the curve radius"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_stretch_to(BlenderRNA *brna) @@ -1888,6 +1960,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "volume", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "volmode"); RNA_def_property_enum_items(prop, volume_items); @@ -1941,6 +2015,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Volume Variation Smoothness", "Strength of volume stretching clamping"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_clamp_to(BlenderRNA *brna) @@ -1964,6 +2040,8 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bClampToConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_CLAMPTO); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll"); @@ -1983,6 +2061,8 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Cyclic", "Treat curve as cyclic curve (no clamping to curve bounding box)"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_transform(BlenderRNA *brna) @@ -2033,6 +2113,8 @@ static void rna_def_constraint_transform(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "map_from", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "from"); RNA_def_property_enum_items(prop, transform_items); @@ -2323,6 +2405,8 @@ static void rna_def_constraint_transform(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Scale Mix Mode", "Specify how to combine the new scale with original"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_location_limit(BlenderRNA *brna) @@ -2336,6 +2420,8 @@ static void rna_def_constraint_location_limit(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bLocLimitConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_LOCLIMIT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_min_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XMIN); RNA_def_property_ui_text(prop, "Minimum X", "Use the minimum X value"); @@ -2407,6 +2493,8 @@ static void rna_def_constraint_location_limit(BlenderRNA *brna) RNA_def_property_ui_text( prop, "For Transform", "Transforms are affected by this constraint as well"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_rotation_limit(BlenderRNA *brna) @@ -2420,6 +2508,8 @@ static void rna_def_constraint_rotation_limit(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bRotLimitConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_ROTLIMIT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_limit_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XROT); RNA_def_property_ui_text(prop, "Limit X", "Use the minimum X value"); @@ -2476,6 +2566,8 @@ static void rna_def_constraint_rotation_limit(BlenderRNA *brna) RNA_def_property_ui_text( prop, "For Transform", "Transforms are affected by this constraint as well"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_size_limit(BlenderRNA *brna) @@ -2489,6 +2581,8 @@ static void rna_def_constraint_size_limit(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bSizeLimitConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_SIZELIMIT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_min_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XMIN); RNA_def_property_ui_text(prop, "Minimum X", "Use the minimum X value"); @@ -2560,6 +2654,8 @@ static void rna_def_constraint_size_limit(BlenderRNA *brna) RNA_def_property_ui_text( prop, "For Transform", "Transforms are affected by this constraint as well"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_distance_limit(BlenderRNA *brna) @@ -2578,6 +2674,8 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "dist"); RNA_def_property_ui_range(prop, 0.0f, 100.0f, 10, 3); @@ -2596,6 +2694,8 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna) RNA_def_property_ui_text( prop, "For Transform", "Transforms are affected by this constraint as well"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) @@ -2649,6 +2749,8 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bShrinkwrapConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_SHRINKWRAP); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO, mesh type */ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll"); @@ -2734,6 +2836,8 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) RNA_def_property_enum_items(prop, track_axis_items); RNA_def_property_ui_text(prop, "Track Axis", "Axis that is aligned to the normal"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_damped_track(BlenderRNA *brna) @@ -2752,11 +2856,15 @@ static void rna_def_constraint_damped_track(BlenderRNA *brna) rna_def_constraint_target_common(srna); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "trackflag"); RNA_def_property_enum_items(prop, track_axis_items); RNA_def_property_ui_text(prop, "Track Axis", "Axis that points to the target object"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_spline_ik(BlenderRNA *brna) @@ -2804,6 +2912,8 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bSplineIKConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_SPLINEIK); + RNA_define_lib_overridable(true); + /* target chain */ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); @@ -2922,6 +3032,8 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Volume Variation Smoothness", "Strength of volume stretching clamping"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_pivot(BlenderRNA *brna) @@ -2973,6 +3085,8 @@ static void rna_def_constraint_pivot(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_CON_PIVOT); + RNA_define_lib_overridable(true); + /* target-defined pivot */ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "tar"); @@ -3011,6 +3125,8 @@ static void rna_def_constraint_pivot(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Enabled Rotation Range", "Rotation range on which pivoting should occur"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_follow_track(BlenderRNA *brna) @@ -3031,6 +3147,8 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bFollowTrackConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_FOLLOWTRACK); + RNA_define_lib_overridable(true); + /* movie clip */ prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clip"); @@ -3106,6 +3224,8 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", FOLLOWTRACK_USE_UNDISTORTION); RNA_def_property_ui_text(prop, "Undistort", "Parent to undistorted position of 2D track"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_camera_solver(BlenderRNA *brna) @@ -3119,6 +3239,8 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bCameraSolverConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_CAMERASOLVER); + RNA_define_lib_overridable(true); + /* movie clip */ prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clip"); @@ -3132,6 +3254,8 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", CAMERASOLVER_ACTIVECLIP); RNA_def_property_ui_text(prop, "Active Clip", "Use active clip defined in scene"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_object_solver(BlenderRNA *brna) @@ -3145,6 +3269,8 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bObjectSolverConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_OBJECTSOLVER); + RNA_define_lib_overridable(true); + /* movie clip */ prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "clip"); @@ -3184,6 +3310,8 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna) "rna_Constraint_objectSolver_camera_set", NULL, "rna_Constraint_cameraObject_poll"); + + RNA_define_lib_overridable(false); } static void rna_def_constraint_transform_cache(BlenderRNA *brna) @@ -3197,6 +3325,8 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna) RNA_def_struct_sdna_from(srna, "bTransformCacheConstraint", "data"); RNA_def_struct_ui_icon(srna, ICON_CON_TRANSFORM_CACHE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "cache_file"); RNA_def_property_struct_type(prop, "CacheFile"); @@ -3211,6 +3341,8 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna) "Object Path", "Path to the object in the Alembic archive used to lookup the transform matrix"); RNA_def_property_update(prop, 0, "rna_Constraint_update"); + + RNA_define_lib_overridable(false); } /* base struct for constraints */ @@ -3241,6 +3373,8 @@ void RNA_def_constraint(BlenderRNA *brna) RNA_def_property_enum_items(prop, rna_enum_constraint_type_items); RNA_def_property_ui_text(prop, "Type", ""); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "owner_space", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "ownspace"); RNA_def_property_enum_items(prop, owner_space_pchan_items); @@ -3258,7 +3392,6 @@ void RNA_def_constraint(BlenderRNA *brna) /* flags */ prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_OFF); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Disable", "Enable/Disable Constraint"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1); @@ -3266,7 +3399,6 @@ void RNA_def_constraint(BlenderRNA *brna) prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_EXPAND); - RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Expanded", "Constraint's panel is expanded in UI"); RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1); @@ -3315,6 +3447,8 @@ void RNA_def_constraint(BlenderRNA *brna) "Rot error", "Amount of residual error in radians for constraints that work on orientation"); + RNA_define_lib_overridable(false); + /* pointers */ rna_def_constrainttarget(brna); rna_def_constrainttarget_bone(brna); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 7a439a11a54..f59a1790e7b 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -61,7 +61,18 @@ static CLG_LogRef LOG = {"rna.define"}; /* Global used during defining */ -BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1}; +BlenderDefRNA DefRNA = { + .sdna = NULL, + .structs = {NULL, NULL}, + .allocs = {NULL, NULL}, + .laststruct = NULL, + .error = 0, + .silent = false, + .preprocess = false, + .verify = true, + .animate = true, + .make_overridable = false, +}; #ifndef RNA_RUNTIME static struct { @@ -691,13 +702,13 @@ BlenderRNA *RNA_create(void) BLI_listbase_clear(&DefRNA.structs); brna->structs_map = BLI_ghash_str_new_ex(__func__, 2048); - DefRNA.error = 0; - DefRNA.preprocess = 1; + DefRNA.error = false; + DefRNA.preprocess = true; DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, &error_message); if (DefRNA.sdna == NULL) { CLOG_ERROR(&LOG, "Failed to decode SDNA: %s.", error_message); - DefRNA.error = 1; + DefRNA.error = true; } /* We need both alias and static (on-disk) DNA names. */ @@ -737,7 +748,7 @@ void RNA_define_free(BlenderRNA *UNUSED(brna)) DefRNA.sdna = NULL; } - DefRNA.error = 0; + DefRNA.error = false; } void RNA_define_verify_sdna(bool verify) @@ -745,6 +756,15 @@ void RNA_define_verify_sdna(bool verify) DefRNA.verify = verify; } +/** + * Properties defined when this is enabled are lib-overridable by default (except for Pointer + * ones). + */ +void RNA_define_lib_overridable(const bool make_overridable) +{ + DefRNA.make_overridable = make_overridable; +} + #ifndef RNA_RUNTIME void RNA_define_animate_sdna(bool animate) { @@ -910,7 +930,7 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN if (rna_validate_identifier(identifier, error, false) == 0) { CLOG_ERROR(&LOG, "struct identifier \"%s\" error - %s", identifier, error); - DefRNA.error = 1; + DefRNA.error = true; } } @@ -1040,7 +1060,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char * srnafrom = BLI_ghash_lookup(brna->structs_map, from); if (!srnafrom) { CLOG_ERROR(&LOG, "struct %s not found to define %s.", from, identifier); - DefRNA.error = 1; + DefRNA.error = true; } } @@ -1065,7 +1085,7 @@ void RNA_def_struct_sdna(StructRNA *srna, const char *structname) if (DNA_struct_find_nr_wrapper(DefRNA.sdna, structname) == -1) { if (!DefRNA.silent) { CLOG_ERROR(&LOG, "%s not found.", structname); - DefRNA.error = 1; + DefRNA.error = true; } return; } @@ -1093,7 +1113,7 @@ void RNA_def_struct_sdna_from(StructRNA *srna, const char *structname, const cha if (DNA_struct_find_nr_wrapper(DefRNA.sdna, structname) == -1) { if (!DefRNA.silent) { CLOG_ERROR(&LOG, "%s not found.", structname); - DefRNA.error = 1; + DefRNA.error = true; } return; } @@ -1106,7 +1126,7 @@ void RNA_def_struct_name_property(struct StructRNA *srna, struct PropertyRNA *pr { if (prop->type != PROP_STRING) { CLOG_ERROR(&LOG, "\"%s.%s\", must be a string property.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } else { srna->nameproperty = prop; @@ -1121,7 +1141,7 @@ void RNA_def_struct_nested(BlenderRNA *brna, StructRNA *srna, const char *struct srnafrom = BLI_ghash_lookup(brna->structs_map, structname); if (!srnafrom) { CLOG_ERROR(&LOG, "struct %s not found for %s.", structname, srna->identifier); - DefRNA.error = 1; + DefRNA.error = true; } srna->nested = srnafrom; @@ -1271,7 +1291,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, if (rna_validate_identifier(identifier, error, true) == 0) { CLOG_ERROR( &LOG, "property identifier \"%s.%s\" - %s", CONTAINER_RNA_ID(cont), identifier, error); - DefRNA.error = 1; + DefRNA.error = true; } dcont = rna_find_container_def(cont); @@ -1279,7 +1299,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, /* XXX - toto, detect supertype collisions */ if (rna_findlink(&dcont->properties, identifier)) { CLOG_ERROR(&LOG, "duplicate identifier \"%s.%s\"", CONTAINER_RNA_ID(cont), identifier); - DefRNA.error = 1; + DefRNA.error = true; } dprop = MEM_callocN(sizeof(PropertyDefRNA), "PropertyDefRNA"); @@ -1294,7 +1314,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, CONTAINER_RNA_ID(cont), identifier, error); - DefRNA.error = 1; + DefRNA.error = true; } #endif } @@ -1309,7 +1329,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, "subtype does not apply to 'PROP_BOOLEAN' \"%s.%s\"", CONTAINER_RNA_ID(cont), identifier); - DefRNA.error = 1; + DefRNA.error = true; } } break; @@ -1322,7 +1342,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, "subtype does not apply to 'PROP_INT' \"%s.%s\"", CONTAINER_RNA_ID(cont), identifier); - DefRNA.error = 1; + DefRNA.error = true; } #endif @@ -1371,7 +1391,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, break; default: CLOG_ERROR(&LOG, "\"%s.%s\", invalid property type.", CONTAINER_RNA_ID(cont), identifier); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } @@ -1404,6 +1424,14 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, } } +#ifndef RNA_RUNTIME + if (type != PROP_POINTER) { + if (DefRNA.make_overridable) { + prop->flag_override |= PROPOVERRIDE_OVERRIDABLE_LIBRARY; + } + } +#endif + if (type == PROP_STRING) { /* used so generated 'get/length/set' functions skip a NULL check * in some cases we want it */ @@ -1413,42 +1441,42 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, if (DefRNA.preprocess) { switch (type) { case PROP_BOOLEAN: - DefRNA.silent = 1; + DefRNA.silent = true; RNA_def_property_boolean_sdna(prop, NULL, identifier, 0); - DefRNA.silent = 0; + DefRNA.silent = false; break; case PROP_INT: { - DefRNA.silent = 1; + DefRNA.silent = true; RNA_def_property_int_sdna(prop, NULL, identifier); - DefRNA.silent = 0; + DefRNA.silent = false; break; } case PROP_FLOAT: { - DefRNA.silent = 1; + DefRNA.silent = true; RNA_def_property_float_sdna(prop, NULL, identifier); - DefRNA.silent = 0; + DefRNA.silent = false; break; } case PROP_STRING: { - DefRNA.silent = 1; + DefRNA.silent = true; RNA_def_property_string_sdna(prop, NULL, identifier); - DefRNA.silent = 0; + DefRNA.silent = false; break; } case PROP_ENUM: - DefRNA.silent = 1; + DefRNA.silent = true; RNA_def_property_enum_sdna(prop, NULL, identifier); - DefRNA.silent = 0; + DefRNA.silent = false; break; case PROP_POINTER: - DefRNA.silent = 1; + DefRNA.silent = true; RNA_def_property_pointer_sdna(prop, NULL, identifier); - DefRNA.silent = 0; + DefRNA.silent = false; break; case PROP_COLLECTION: - DefRNA.silent = 1; + DefRNA.silent = true; RNA_def_property_collection_sdna(prop, NULL, identifier, NULL); - DefRNA.silent = 0; + DefRNA.silent = false; break; } } @@ -1543,7 +1571,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length) "\"%s.%s\", array length must be zero of greater.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -1553,7 +1581,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length) srna->identifier, prop->identifier, RNA_MAX_ARRAY_LENGTH); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -1563,7 +1591,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length) srna->identifier, prop->identifier, prop->arraydimension); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -1580,7 +1608,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length) "\"%s.%s\", only boolean/int/float can be array.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1606,7 +1634,7 @@ void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int le srna->identifier, prop->identifier, RNA_MAX_ARRAY_DIMENSION); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -1620,7 +1648,7 @@ void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int le "\"%s.%s\", only boolean/int/float can be array.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } @@ -1680,22 +1708,22 @@ void RNA_def_property_ui_range( #ifndef NDEBUG if (min > max) { CLOG_ERROR(&LOG, "\"%s.%s\", min > max.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } if (step < 0 || step > 100) { CLOG_ERROR(&LOG, "\"%s.%s\", step outside range.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } if (step == 0) { CLOG_ERROR(&LOG, "\"%s.%s\", step is zero.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } if (precision < -1 || precision > UI_PRECISION_FLOAT_MAX) { CLOG_ERROR(&LOG, "\"%s.%s\", precision outside range.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } #endif @@ -1718,7 +1746,7 @@ void RNA_def_property_ui_range( default: CLOG_ERROR( &LOG, "\"%s.%s\", invalid type for ui range.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1730,7 +1758,7 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max) #ifdef DEBUG if (min > max) { CLOG_ERROR(&LOG, "\"%s.%s\", min > max.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } #endif @@ -1753,7 +1781,7 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max) } default: CLOG_ERROR(&LOG, "\"%s.%s\", invalid type for range.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1781,7 +1809,7 @@ void RNA_def_property_struct_type(PropertyRNA *prop, const char *type) default: CLOG_ERROR( &LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1814,7 +1842,7 @@ void RNA_def_property_struct_runtime(PropertyRNA *prop, StructRNA *type) default: CLOG_ERROR( &LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1831,7 +1859,7 @@ void RNA_def_property_enum_native_type(PropertyRNA *prop, const char *native_enu default: CLOG_ERROR( &LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1856,7 +1884,7 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item "\"%s.%s\", enum identifiers must not contain spaces.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } else if (item[i].value == eprop->defaultvalue) { @@ -1879,7 +1907,7 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item default: CLOG_ERROR( &LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1896,7 +1924,7 @@ void RNA_def_property_string_maxlength(PropertyRNA *prop, int maxlength) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1920,7 +1948,7 @@ void RNA_def_property_boolean_default(PropertyRNA *prop, bool value) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1937,7 +1965,7 @@ void RNA_def_property_boolean_array_default(PropertyRNA *prop, const bool *array } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1959,7 +1987,7 @@ void RNA_def_property_int_default(PropertyRNA *prop, int value) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -1981,7 +2009,7 @@ void RNA_def_property_int_array_default(PropertyRNA *prop, const int *array) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -2003,7 +2031,7 @@ void RNA_def_property_float_default(PropertyRNA *prop, float value) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -2025,7 +2053,7 @@ void RNA_def_property_float_array_default(PropertyRNA *prop, const float *array) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -2043,7 +2071,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value) "\"%s.%s\", NULL string passed (dont call in this case).", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } @@ -2052,7 +2080,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value) "\"%s.%s\", empty string passed (dont call in this case).", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; // BLI_assert(0); break; } @@ -2066,7 +2094,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -2096,7 +2124,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value) srna->identifier, prop->identifier, eprop->defaultvalue & ~totflag); - DefRNA.error = 1; + DefRNA.error = true; } } else { @@ -2113,7 +2141,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value) else { CLOG_ERROR( &LOG, "\"%s.%s\", default is not in items.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; } } } @@ -2122,7 +2150,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value) } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -2175,7 +2203,7 @@ static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop, structname, propname, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return NULL; } } @@ -2219,13 +2247,13 @@ void RNA_def_property_boolean_sdna(PropertyRNA *prop, if (prop->type != PROP_BOOLEAN) { CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } if ((dp = rna_def_property_sdna(prop, structname, propname))) { - if (DefRNA.silent == 0) { + if (!DefRNA.silent) { /* error check to ensure floats are not wrapped as ints/bools */ if (dp->dnatype && *dp->dnatype && IS_DNATYPE_BOOLEAN_COMPAT(dp->dnatype) == 0) { CLOG_ERROR(&LOG, @@ -2234,7 +2262,7 @@ void RNA_def_property_boolean_sdna(PropertyRNA *prop, prop->identifier, dp->dnatype, RNA_property_typename(prop->type)); - DefRNA.error = 1; + DefRNA.error = true; return; } } @@ -2323,14 +2351,14 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const if (prop->type != PROP_INT) { CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } if ((dp = rna_def_property_sdna(prop, structname, propname))) { /* error check to ensure floats are not wrapped as ints/bools */ - if (DefRNA.silent == 0) { + if (!DefRNA.silent) { if (dp->dnatype && *dp->dnatype && IS_DNATYPE_INT_COMPAT(dp->dnatype) == 0) { CLOG_ERROR(&LOG, "%s.%s is a '%s' but wrapped as type '%s'.", @@ -2338,7 +2366,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const prop->identifier, dp->dnatype, RNA_property_typename(prop->type)); - DefRNA.error = 1; + DefRNA.error = true; return; } } @@ -2470,13 +2498,13 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons if (prop->type != PROP_FLOAT) { CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } if ((dp = rna_def_property_sdna(prop, structname, propname))) { /* silent is for internal use */ - if (DefRNA.silent == 0) { + if (!DefRNA.silent) { if (dp->dnatype && *dp->dnatype && IS_DNATYPE_FLOAT_COMPAT(dp->dnatype) == 0) { /* Colors are an exception. these get translated. */ if (prop->subtype != PROP_COLOR_GAMMA) { @@ -2486,7 +2514,7 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons prop->identifier, dp->dnatype, RNA_property_typename(prop->type)); - DefRNA.error = 1; + DefRNA.error = true; return; } } @@ -2578,7 +2606,7 @@ void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const if (prop->type != PROP_ENUM) { CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -2589,7 +2617,7 @@ void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const if (!DefRNA.silent) { CLOG_ERROR(&LOG, "\"%s.%s\", array not supported for enum type.", structname, propname); - DefRNA.error = 1; + DefRNA.error = true; } } @@ -2672,7 +2700,7 @@ void RNA_def_property_string_sdna(PropertyRNA *prop, const char *structname, con if (prop->type != PROP_STRING) { CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -2716,7 +2744,7 @@ void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, co if (prop->type != PROP_POINTER) { CLOG_ERROR(&LOG, "\"%s.%s\", type is not pointer.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -2727,7 +2755,7 @@ void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, co if (!DefRNA.silent) { CLOG_ERROR(&LOG, "\"%s.%s\", array not supported for pointer type.", structname, propname); - DefRNA.error = 1; + DefRNA.error = true; } } } @@ -2749,7 +2777,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop, if (prop->type != PROP_COLLECTION) { CLOG_ERROR(&LOG, "\"%s.%s\", type is not collection.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -2760,7 +2788,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop, if (!DefRNA.silent) { CLOG_ERROR(&LOG, "\"%s.%s\", array of collections not supported.", structname, propname); - DefRNA.error = 1; + DefRNA.error = true; } } @@ -2806,7 +2834,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop, else { if (!DefRNA.silent) { CLOG_ERROR(&LOG, "\"%s.%s\" not found.", structname, lengthpropname); - DefRNA.error = 1; + DefRNA.error = true; } } } @@ -2904,7 +2932,7 @@ void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getleng if (!(prop->flag & PROP_DYNAMIC)) { CLOG_ERROR(&LOG, "property is a not dynamic array."); - DefRNA.error = 1; + DefRNA.error = true; return; } @@ -2946,7 +2974,7 @@ void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const ch } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -3036,7 +3064,7 @@ void RNA_def_property_int_funcs(PropertyRNA *prop, } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -3134,7 +3162,7 @@ void RNA_def_property_float_funcs(PropertyRNA *prop, } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -3222,7 +3250,7 @@ void RNA_def_property_enum_funcs(PropertyRNA *prop, } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -3289,7 +3317,7 @@ void RNA_def_property_string_funcs(PropertyRNA *prop, } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -3351,7 +3379,7 @@ void RNA_def_property_pointer_funcs( } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not pointer.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -3405,7 +3433,7 @@ void RNA_def_property_collection_funcs(PropertyRNA *prop, } default: CLOG_ERROR(&LOG, "\"%s.%s\", type is not collection.", srna->identifier, prop->identifier); - DefRNA.error = 1; + DefRNA.error = true; break; } } @@ -4170,7 +4198,7 @@ static FunctionRNA *rna_def_function(StructRNA *srna, const char *identifier) if (rna_validate_identifier(identifier, error, false) == 0) { CLOG_ERROR(&LOG, "function identifier \"%s\" - %s", identifier, error); - DefRNA.error = 1; + DefRNA.error = true; } } diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 93c7c1f3480..43d2234ddf2 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -227,8 +227,11 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FLIP); - /* Only create a particle system in liquid domain mode. */ + /* Only create a particle system in liquid domain mode. + * Remove any remainings of a liquid sim when switching to gas. */ if (mmd->domain->type != FLUID_DOMAIN_TYPE_LIQUID) { + rna_Fluid_parts_delete(ptr, PART_FLUID_FLIP); + mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP; rna_Fluid_domain_reset(bmain, scene, ptr); return; } diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 9faf589fe8a..6afa740fec3 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -118,7 +118,14 @@ typedef struct BlenderDefRNA { ListBase structs; ListBase allocs; struct StructRNA *laststruct; - int error, silent, preprocess, verify, animate; + bool error; + bool silent; + bool preprocess; + bool verify; + bool animate; + /** Whether RNA properties defined should be overridable or not by default. */ + bool make_overridable; + /* Keep last. */ #ifndef RNA_RUNTIME struct { diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c index c19dafb3bc6..2caf315e09e 100644 --- a/source/blender/makesrna/intern/rna_light.c +++ b/source/blender/makesrna/intern/rna_light.c @@ -186,25 +186,45 @@ static void rna_def_light(BlenderRNA *brna) rna_def_animdata_common(srna); } -static void rna_def_light_energy(StructRNA *srna, bool distant) +static void rna_def_light_energy(StructRNA *srna, const short light_type) { PropertyRNA *prop; - if (distant) { - /* Distant light strength has no unit defined, it's proportional to - * Watt/m^2 and is not sensitive to scene unit scale. */ - prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE); - RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3); - RNA_def_property_ui_text(prop, "Strength", "Amount of light emitted"); - RNA_def_property_update(prop, 0, "rna_Light_draw_update"); - } - else { - /* Lights with a location have power in Watt, which is sensitive to - * scene unit scale. */ - prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER); - RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5); - RNA_def_property_ui_text(prop, "Power", "Amount of light emitted"); - RNA_def_property_update(prop, 0, "rna_Light_draw_update"); + switch (light_type) { + case LA_SUN: { + /* Distant light strength has no unit defined, + * it's proportional to 'watt/m^2' and is not sensitive to scene unit scale. */ + prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3); + RNA_def_property_ui_text( + prop, "Strength", "Sunlight strength in watts per meter squared (W/m^2)"); + RNA_def_property_update(prop, 0, "rna_Light_draw_update"); + break; + } + case LA_SPOT: { + /* Lights with a location have power in Watts, + * which is sensitive to scene unit scale. */ + prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER); + RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5); + RNA_def_property_ui_text(prop, + "Power", + "The energy this light would emit over its entire area " + "if it wasn't limited by the spot angle"); + RNA_def_property_update(prop, 0, "rna_Light_draw_update"); + break; + } + default: { + /* Lights with a location have power in Watts, + * which is sensitive to scene unit scale. */ + prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER); + RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5); + RNA_def_property_ui_text( + prop, + "Power", + "Light energy emitted over the entire area of the light in all directions"); + RNA_def_property_update(prop, 0, "rna_Light_draw_update"); + break; + } } } @@ -395,7 +415,7 @@ static void rna_def_point_light(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Point Light", "Omnidirectional point Light"); RNA_def_struct_ui_icon(srna, ICON_LIGHT_POINT); - rna_def_light_energy(srna, false); + rna_def_light_energy(srna, LA_LOCAL); rna_def_light_falloff(srna); rna_def_light_shadow(srna, false); } @@ -418,7 +438,7 @@ static void rna_def_area_light(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Area Light", "Directional area Light"); RNA_def_struct_ui_icon(srna, ICON_LIGHT_AREA); - rna_def_light_energy(srna, false); + rna_def_light_energy(srna, LA_AREA); rna_def_light_shadow(srna, false); rna_def_light_falloff(srna); @@ -457,7 +477,7 @@ static void rna_def_spot_light(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Spot Light", "Directional cone Light"); RNA_def_struct_ui_icon(srna, ICON_LIGHT_SPOT); - rna_def_light_energy(srna, false); + rna_def_light_energy(srna, LA_SPOT); rna_def_light_falloff(srna); rna_def_light_shadow(srna, false); @@ -503,7 +523,7 @@ static void rna_def_sun_light(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Angle", "Angular diameter of the Sun as seen from the Earth"); RNA_def_property_update(prop, 0, "rna_Light_update"); - rna_def_light_energy(srna, true); + rna_def_light_energy(srna, LA_SUN); rna_def_light_shadow(srna, true); } diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index f5a437b7892..1e21278c8eb 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1682,6 +1682,8 @@ static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const c PropertyRNA *prop; + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "uv_smooth", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "uv_smooth"); RNA_def_property_enum_items(prop, prop_uv_smooth_items); @@ -1702,6 +1704,8 @@ static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const c RNA_def_property_ui_text(prop, "Subdivision Type", "Select type of subdivision algorithm"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + RNA_define_lib_overridable(false); + return prop; } @@ -1717,6 +1721,8 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) rna_def_property_subdivision_common(srna, "subdivType"); + RNA_define_lib_overridable(true); + /* see CCGSUBSURF_LEVEL_MAX for max limit */ prop = RNA_def_property(srna, "levels", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "levels"); @@ -1743,6 +1749,8 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Creases", "Use mesh edge crease information to sharpen edges"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_generic_map_info(StructRNA *srna) @@ -1769,6 +1777,8 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna) PropertyRNA *prop; + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Texture", ""); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -1799,6 +1809,8 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna) RNA_def_property_string_sdna(prop, NULL, "map_bone"); RNA_def_property_ui_text(prop, "Texture Coordinate Bone", "Bone to set the texture coordinates"); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_warp(BlenderRNA *brna) @@ -1811,6 +1823,8 @@ static void rna_def_modifier_warp(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WarpModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_WARP); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "object_from"); RNA_def_property_ui_text(prop, "Object From", "Object to transform from"); @@ -1872,6 +1886,8 @@ static void rna_def_modifier_warp(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + RNA_define_lib_overridable(false); + rna_def_modifier_generic_map_info(srna); } @@ -1885,6 +1901,8 @@ static void rna_def_modifier_multires(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MultiresModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MULTIRES); + RNA_define_lib_overridable(true); + prop = rna_def_property_subdivision_common(srna, "simple"); RNA_def_property_enum_funcs(prop, NULL, "rna_MultiresModifier_type_set", NULL); @@ -1936,6 +1954,8 @@ static void rna_def_modifier_multires(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Creases", "Use mesh edge crease information to sharpen edges"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_lattice(BlenderRNA *brna) @@ -1948,6 +1968,8 @@ static void rna_def_modifier_lattice(BlenderRNA *brna) RNA_def_struct_sdna(srna, "LatticeModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_LATTICE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Object", "Lattice object to deform with"); RNA_def_property_pointer_funcs( @@ -1975,6 +1997,8 @@ static void rna_def_modifier_lattice(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 1, 10, 2); RNA_def_property_ui_text(prop, "Strength", "Strength of modifier effect"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_curve(BlenderRNA *brna) @@ -1997,6 +2021,8 @@ static void rna_def_modifier_curve(BlenderRNA *brna) RNA_def_struct_sdna(srna, "CurveModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_CURVE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Object", "Curve object to deform with"); RNA_def_property_pointer_funcs( @@ -2024,6 +2050,8 @@ static void rna_def_modifier_curve(BlenderRNA *brna) RNA_def_property_enum_items(prop, prop_deform_axis_items); RNA_def_property_ui_text(prop, "Deform Axis", "The axis that the curve deforms along"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_build(BlenderRNA *brna) @@ -2036,6 +2064,8 @@ static void rna_def_modifier_build(BlenderRNA *brna) RNA_def_struct_sdna(srna, "BuildModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_BUILD); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME); RNA_def_property_float_sdna(prop, NULL, "start"); RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF); @@ -2062,6 +2092,8 @@ static void rna_def_modifier_build(BlenderRNA *brna) RNA_def_property_range(prop, 1, MAXFRAMEF); RNA_def_property_ui_text(prop, "Seed", "Seed for random if used"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_mirror(BlenderRNA *brna) @@ -2074,6 +2106,8 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MirrorModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MIRROR); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_axis", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_AXIS_X); RNA_def_property_array(prop, 3); @@ -2174,6 +2208,8 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_decimate(BlenderRNA *brna) @@ -2199,6 +2235,8 @@ static void rna_def_modifier_decimate(BlenderRNA *brna) RNA_def_struct_sdna(srna, "DecimateModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_DECIM); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "decimate_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, modifier_decim_mode_items); @@ -2287,6 +2325,8 @@ static void rna_def_modifier_decimate(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text( prop, "Face Count", "The current number of faces in the decimated mesh"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_wave(BlenderRNA *brna) @@ -2299,6 +2339,8 @@ static void rna_def_modifier_wave(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WaveModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_WAVE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WAVE_X); RNA_def_property_ui_text(prop, "X", "X axis motion"); @@ -2426,6 +2468,8 @@ static void rna_def_modifier_wave(BlenderRNA *brna) "the more narrow the wave"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + RNA_define_lib_overridable(false); + rna_def_modifier_generic_map_info(srna); } @@ -2439,6 +2483,8 @@ static void rna_def_modifier_armature(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ArmatureModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_ARMATURE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Object", "Armature object to deform with"); RNA_def_property_pointer_funcs( @@ -2486,6 +2532,8 @@ static void rna_def_modifier_armature(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "deformflag", ARM_DEF_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_hook(BlenderRNA *brna) @@ -2501,6 +2549,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna) RNA_def_struct_sdna(srna, "HookModifierData"); RNA_def_struct_ui_icon(srna, ICON_HOOK); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "force"); RNA_def_property_range(prop, 0, 1); @@ -2595,6 +2645,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_HOOK_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_softbody(BlenderRNA *brna) @@ -2645,6 +2697,8 @@ static void rna_def_modifier_boolean(BlenderRNA *brna) RNA_def_struct_sdna(srna, "BooleanModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_BOOLEAN); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Object", "Mesh object to use for Boolean operation"); RNA_def_property_pointer_funcs( @@ -2687,6 +2741,8 @@ static void rna_def_modifier_boolean(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_ENUM_FLAG); RNA_def_property_ui_text(prop, "Debug", "Debugging options, only when started with '-d'"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_array(BlenderRNA *brna) @@ -2714,6 +2770,8 @@ static void rna_def_modifier_array(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ArrayModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_ARRAY); + RNA_define_lib_overridable(true); + /* Length parameters */ prop = RNA_def_property(srna, "fit_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_fit_type_items); @@ -2836,6 +2894,8 @@ static void rna_def_modifier_array(BlenderRNA *brna) RNA_def_property_ui_range(prop, -1, 1, 2, 4); RNA_def_property_ui_text(prop, "V Offset", "Amount to offset array UVs on the V axis"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_edgesplit(BlenderRNA *brna) @@ -2849,6 +2909,8 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna) RNA_def_struct_sdna(srna, "EdgeSplitModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_EDGESPLIT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f)); RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 2); @@ -2864,6 +2926,8 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_EDGESPLIT_FROMFLAG); RNA_def_property_ui_text(prop, "Use Sharp Edges", "Split edges that are marked as sharp"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_displace(BlenderRNA *brna) @@ -2917,6 +2981,8 @@ static void rna_def_modifier_displace(BlenderRNA *brna) RNA_def_struct_sdna(srna, "DisplaceModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_DISPLACE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); RNA_def_property_ui_text( @@ -2954,6 +3020,8 @@ static void rna_def_modifier_displace(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + RNA_define_lib_overridable(false); + rna_def_modifier_generic_map_info(srna); } @@ -3049,6 +3117,8 @@ static void rna_def_modifier_smooth(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SmoothModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SMOOTH_X); RNA_def_property_ui_text(prop, "X", "Smooth object along X axis"); @@ -3090,6 +3160,8 @@ static void rna_def_modifier_smooth(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SMOOTH_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_correctivesmooth(BlenderRNA *brna) @@ -3131,6 +3203,8 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna) RNA_def_struct_sdna(srna, "CorrectiveSmoothModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "lambda"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); @@ -3194,6 +3268,8 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Pin Boundaries", "Excludes boundary vertices from being smoothed"); RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) @@ -3206,6 +3282,8 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_struct_sdna(srna, "LaplacianSmoothModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_X); RNA_def_property_ui_text(prop, "X", "Smooth object along X axis"); @@ -3264,6 +3342,8 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_cast(BlenderRNA *brna) @@ -3283,6 +3363,8 @@ static void rna_def_modifier_cast(BlenderRNA *brna) RNA_def_struct_sdna(srna, "CastModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_CAST); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "cast_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_cast_type_items); @@ -3359,6 +3441,8 @@ static void rna_def_modifier_cast(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CastModifier_defgrp_name_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_meshdeform(BlenderRNA *brna) @@ -3379,6 +3463,8 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MeshDeformModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Object", "Mesh object to deform with"); RNA_def_property_pointer_funcs( @@ -3423,6 +3509,8 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Mode", "Method of binding vertices are bound to cage mesh"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); # endif + + RNA_define_lib_overridable(false); } static void rna_def_modifier_particlesystem(BlenderRNA *brna) @@ -3438,6 +3526,7 @@ static void rna_def_modifier_particlesystem(BlenderRNA *brna) prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "psys"); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Particle System", "Particle System that this modifier controls"); } @@ -3465,6 +3554,8 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ParticleInstanceModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "ob"); RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll"); @@ -3592,6 +3683,8 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Value Layer Name", "Custom data layer name for the randomized value"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_explode(BlenderRNA *brna) @@ -3605,6 +3698,8 @@ static void rna_def_modifier_explode(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ExplodeModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_EXPLODE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_ExplodeModifier_vgroup_get", @@ -3652,6 +3747,8 @@ static void rna_def_modifier_explode(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", eExplodeFlag_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_cloth(BlenderRNA *brna) @@ -3664,6 +3761,8 @@ static void rna_def_modifier_cloth(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ClothModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_CLOTH); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "sim_parms"); @@ -3697,6 +3796,8 @@ static void rna_def_modifier_cloth(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "hair_grid_res"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Hair Grid Resolution", ""); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_fluid(BlenderRNA *brna) @@ -3717,6 +3818,8 @@ static void rna_def_modifier_fluid(BlenderRNA *brna) RNA_def_struct_sdna(srna, "FluidModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_FLUIDSIM); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "domain_settings", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "domain"); RNA_def_property_ui_text(prop, "Domain Settings", ""); @@ -3735,6 +3838,8 @@ static void rna_def_modifier_fluid(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Type", ""); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_fluid_set_type"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_dynamic_paint(BlenderRNA *brna) @@ -3863,6 +3968,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna) RNA_def_struct_sdna(srna, "BevelModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_BEVEL); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "width", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "value"); RNA_def_property_range(prop, 0, FLT_MAX); @@ -4000,6 +4107,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Vertex Mesh Method", "The method to use to create the mesh at intersections"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) @@ -4054,6 +4163,8 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ShrinkwrapModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SHRINKWRAP); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "wrap_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "shrinkType"); RNA_def_property_enum_items(prop, shrink_type_items); @@ -4164,6 +4275,8 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "shrinkOpts", MOD_SHRINKWRAP_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_mask(BlenderRNA *brna) @@ -4182,6 +4295,8 @@ static void rna_def_modifier_mask(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MaskModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MASK); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, modifier_mask_mode_items); RNA_def_property_ui_text(prop, "Mode", ""); @@ -4213,6 +4328,8 @@ static void rna_def_modifier_mask(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0, 1, 0.1, 3); RNA_def_property_ui_text(prop, "Threshold", "Weights over this threshold remain"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_simpledeform(BlenderRNA *brna) @@ -4252,6 +4369,8 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SimpleDeformModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SIMPLEDEFORM); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "deform_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, simple_deform_mode_items); @@ -4316,6 +4435,8 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SIMPLEDEFORM_FLAG_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_surface(BlenderRNA *brna) @@ -4392,6 +4513,8 @@ static void rna_def_modifier_solidify(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SolidifyModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SOLIDIFY); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "solidify_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, mode_items); @@ -4562,6 +4685,8 @@ static void rna_def_modifier_solidify(BlenderRNA *brna) RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3); RNA_def_property_ui_text(prop, "Bevel Convex", "Edge bevel weight to be added to outside edges"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_screw(BlenderRNA *brna) @@ -4574,6 +4699,8 @@ static void rna_def_modifier_screw(BlenderRNA *brna) RNA_def_struct_sdna(srna, "ScrewModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SCREW); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "ob_axis"); RNA_def_property_ui_text(prop, "Object", "Object to define the screw axis"); @@ -4672,6 +4799,8 @@ static void rna_def_modifier_screw(BlenderRNA *brna) prop, "Object Angle", "Use the angle between the objects rather than the fixed angle"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); # endif + + RNA_define_lib_overridable(false); } static void rna_def_modifier_uvwarp(BlenderRNA *brna) @@ -4684,6 +4813,8 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna) RNA_def_struct_sdna(srna, "UVWarpModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "axis_u", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "axis_u"); RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items); @@ -4756,10 +4887,13 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna) RNA_def_property_ui_text(prop, "UV Layer", "UV Layer name"); RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVWarpModifier_uvlayer_name_set"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), StructRNA *srna, + const char *mask_flags, const char *mask_vgroup_setter, const char *mask_uvlayer_setter) { @@ -4789,6 +4923,8 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), PropertyRNA *prop; + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mask_constant", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1); @@ -4802,6 +4938,11 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), RNA_def_property_string_funcs(prop, NULL, NULL, mask_vgroup_setter); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, mask_flags, MOD_WVG_EDIT_INVERT_VGROUP_MASK); + RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Masking Tex", "Masking texture"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -4842,6 +4983,8 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna), RNA_def_property_ui_text( prop, "Texture Coordinate Bone", "Which bone to take texture coordinates from"); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_weightvgedit(BlenderRNA *brna) @@ -4871,6 +5014,8 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WeightVGEditModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name"); @@ -4946,16 +5091,14 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna) "to be removed from the vgroup"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + RNA_define_lib_overridable(false); + /* Common masking properties. */ rna_def_modifier_weightvg_mask(brna, srna, + "edit_flags", "rna_WeightVGEditModifier_mask_defgrp_name_set", "rna_WeightVGEditModifier_mask_tex_uvlayer_name_set"); - - prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_INVERT_VGROUP_MASK); - RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); } static void rna_def_modifier_weightvgmix(BlenderRNA *brna) @@ -5000,6 +5143,8 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WeightVGMixModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "vertex_group_a", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name_a"); RNA_def_property_ui_text(prop, "Vertex Group A", "First vertex group name"); @@ -5053,17 +5198,6 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Vertex Set", "Which vertices should be affected"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - /* Common masking properties. */ - rna_def_modifier_weightvg_mask(brna, - srna, - "rna_WeightVGMixModifier_mask_defgrp_name_set", - "rna_WeightVGMixModifier_mask_tex_uvlayer_name_set"); - - prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_INVERT_VGROUP_MASK); - RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_WEIGHTS_NORMALIZE); RNA_def_property_ui_text( @@ -5071,6 +5205,15 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna) "Normalize Weights", "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); + + /* Common masking properties. */ + rna_def_modifier_weightvg_mask(brna, + srna, + "flag", + "rna_WeightVGMixModifier_mask_defgrp_name_set", + "rna_WeightVGMixModifier_mask_tex_uvlayer_name_set"); } static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) @@ -5124,6 +5267,8 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WeightVGProximityModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "defgrp_name"); RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name"); @@ -5186,17 +5331,14 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna) "Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + RNA_define_lib_overridable(false); + /* Common masking properties. */ rna_def_modifier_weightvg_mask(brna, srna, + "proximity_flags", "rna_WeightVGProximityModifier_mask_defgrp_name_set", "rna_WeightVGProximityModifier_mask_tex_uvlayer_name_set"); - - prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna( - prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK); - RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); } static void rna_def_modifier_remesh(BlenderRNA *brna) @@ -5232,6 +5374,8 @@ static void rna_def_modifier_remesh(BlenderRNA *brna) RNA_def_struct_sdna(srna, "RemeshModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_REMESH); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, mode_items); RNA_def_property_ui_text(prop, "Mode", ""); @@ -5300,6 +5444,8 @@ static void rna_def_modifier_remesh(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Smooth Shading", "Output faces with smooth shading rather than flat shaded"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_ocean(BlenderRNA *brna) @@ -5357,6 +5503,8 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_struct_sdna(srna, "OceanModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_OCEAN); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "geometry_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "geometry_mode"); RNA_def_property_enum_items(prop, geometry_items); @@ -5550,6 +5698,8 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Cache Path", "Path to a folder to store external baked images"); /*RNA_def_property_update(prop, 0, "rna_Modifier_update"); */ /* XXX how to update? */ + + RNA_define_lib_overridable(false); } static void rna_def_modifier_skin(BlenderRNA *brna) @@ -5562,6 +5712,8 @@ static void rna_def_modifier_skin(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SkinModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_SKIN); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "branch_smoothing", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Branch Smoothing", "Smooth complex geometry around branches"); RNA_def_property_ui_range(prop, 0, 1, 1, -1); @@ -5587,6 +5739,8 @@ static void rna_def_modifier_skin(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "symmetry_axes", MOD_SKIN_SYMM_Z); RNA_def_property_ui_text(prop, "Z", "Avoid making unsymmetrical quads across the Z axis"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_triangulate(BlenderRNA *brna) @@ -5599,6 +5753,8 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna) RNA_def_struct_sdna(srna, "TriangulateModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "quad_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "quad_method"); RNA_def_property_enum_items(prop, rna_enum_modifier_triangulate_quad_method_items); @@ -5629,6 +5785,8 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna) "Try to preserve custom normals (WARNING: depending on chosen triangulation method, " "shading may not be fully preserved, 'Fixed' method usually gives the best result here)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_meshcache(BlenderRNA *brna) @@ -5695,6 +5853,8 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MeshCacheModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "cache_format", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, prop_format_type_items); @@ -5789,6 +5949,8 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Evaluation Factor", "Evaluation time in seconds"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_meshseqcache(BlenderRNA *brna) @@ -5801,6 +5963,8 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MeshSeqCacheModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "cache_file"); RNA_def_property_struct_type(prop, "CacheFile"); @@ -5829,6 +5993,8 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "read_flag"); RNA_def_property_enum_items(prop, read_flag_items); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_laplaciandeform(BlenderRNA *brna) @@ -5841,6 +6007,8 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna) RNA_def_struct_sdna(srna, "LaplacianDeformModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "anchor_grp_name"); RNA_def_property_ui_text( @@ -5864,6 +6032,8 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + RNA_define_lib_overridable(false); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); } @@ -5877,6 +6047,8 @@ static void rna_def_modifier_weld(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WeldModifierData"); RNA_def_struct_ui_icon(srna, ICON_AUTOMERGE_OFF); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "merge_dist"); RNA_def_property_range(prop, 0, FLT_MAX); @@ -5904,6 +6076,8 @@ static void rna_def_modifier_weld(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WELD_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_wireframe(BlenderRNA *brna) @@ -5916,6 +6090,8 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WireframeModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_WIREFRAME); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "offset"); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); @@ -5987,6 +6163,8 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WIREFRAME_INVERT_VGROUP); RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_datatransfer(BlenderRNA *brna) @@ -6048,6 +6226,8 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna) RNA_def_struct_sdna(srna, "DataTransferModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_DATA_TRANSFER); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "ob_source"); RNA_def_property_ui_text(prop, "Source Object", "Object to transfer data from"); @@ -6348,6 +6528,8 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna) srna, "invert_vertex_group", false, "Invert", "Invert vertex group influence"); RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_INVERT_VGROUP); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_normaledit(BlenderRNA *brna) @@ -6387,6 +6569,8 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna) RNA_def_struct_sdna(srna, "NormalEditModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, prop_mode_items); RNA_def_property_ui_text(prop, "Mode", "How to affect (generate) normals"); @@ -6469,6 +6653,8 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna) "Use same direction for all normals, from origin to target's center " "(Directional mode only)"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_surfacedeform(BlenderRNA *brna) @@ -6481,6 +6667,8 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SurfaceDeformModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Target", "Mesh object to deform with"); RNA_def_property_pointer_funcs( @@ -6517,6 +6705,8 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna) RNA_def_property_ui_range(prop, -100, 100, 10, 2); RNA_def_property_ui_text(prop, "Strength", "Strength of modifier deformations"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_weightednormal(BlenderRNA *brna) @@ -6548,6 +6738,8 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna) RNA_def_struct_sdna(srna, "WeightedNormalModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT); + RNA_define_lib_overridable(true); + prop = RNA_def_property(srna, "weight", PROP_INT, PROP_NONE); RNA_def_property_range(prop, 1, 100); RNA_def_property_ui_range(prop, 1, 100, 1, -1); @@ -6594,6 +6786,8 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WEIGHTEDNORMAL_FACE_INFLUENCE); RNA_def_property_ui_text(prop, "Face Influence", "Use influence of face for weighting"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } static void rna_def_modifier_simulation_access(BlenderRNA *brna) @@ -6606,6 +6800,8 @@ static void rna_def_modifier_simulation_access(BlenderRNA *brna) RNA_def_struct_sdna(srna, "SimulationModifierData"); RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */ + RNA_define_lib_overridable(true); + # ifdef WITH_NEW_SIMULATION_TYPE prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE); RNA_def_property_ui_text(prop, "Simulation", "Simulation to access"); @@ -6617,6 +6813,8 @@ static void rna_def_modifier_simulation_access(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Data Path", "Identifier of the simulation component that should be accessed"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + RNA_define_lib_overridable(false); } void RNA_def_modifier(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 6c21e4ad01b..6af031eb7b0 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -131,7 +131,7 @@ static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE); GPU_shader_bind(shader); - int img_loc = GPU_shader_get_uniform_ensure(shader, "image"); + int img_loc = GPU_shader_get_uniform(shader, "image"); GPU_shader_uniform_int(shader, img_loc, 0); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index e65d3eb18b0..3dc1d05810c 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2201,12 +2201,12 @@ static void rna_Scene_update_active_object_data(bContext *C, PointerRNA *UNUSED( } } -static void rna_SceneCamera_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *)ptr->owner_id; Object *camera = scene->camera; - BKE_sequence_invalidate_scene_strips(bmain, scene); + BKE_sequencer_cache_cleanup(scene); if (camera && (camera->type == OB_CAMERA)) { DEG_id_tag_update(&camera->id, ID_RECALC_GEOMETRY); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 45d7bc24017..39ea054456f 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -2016,7 +2016,7 @@ static void rna_def_editor(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Prefetch Frames", - "Render frames ahead of playhead in the background for faster playback"); + "Render frames ahead of current frame in the background for faster playback"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); prop = RNA_def_property(srna, "recycle_max_cost", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 2a64ffa73cd..8d0e403aa2d 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -485,6 +485,21 @@ static void rna_uiTemplateAnyID(uiLayout *layout, uiTemplateAnyID(layout, ptr, propname, proptypename, name); } +static void rna_uiTemplateCacheFile(uiLayout *layout, + bContext *C, + PointerRNA *ptr, + const char *propname) +{ + PropertyRNA *prop = RNA_struct_find_property(ptr, propname); + + if (!prop) { + RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + return; + } + + uiTemplateCacheFile(layout, C, ptr, propname); +} + static void rna_uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, @@ -1577,7 +1592,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_float_array( func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f); - func = RNA_def_function(srna, "template_cache_file", "uiTemplateCacheFile"); + func = RNA_def_function(srna, "template_cache_file", "rna_uiTemplateCacheFile"); RNA_def_function_ui_description( func, "Item(s). User interface for selecting cache files and their source paths"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 479d0a0d1a7..49a0121dadb 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -360,7 +360,7 @@ static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene) static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr) { - GPU_set_anisotropic(bmain, U.anisotropic_filter); + GPU_set_anisotropic(U.anisotropic_filter); rna_userdef_update(bmain, scene, ptr); } diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 98c7d809f33..34590736e37 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -922,7 +922,13 @@ static Mesh *subdivide_base(Mesh *orig) u = e->v1; radrat = (half_v2(outnode[e->v2].radius) / half_v2(outnode[e->v1].radius)); - radrat = (radrat + 1) / 2; + if (isfinite(radrat)) { + radrat = (radrat + 1) / 2; + } + else { + /* Happens when skin is scaled to zero. */ + radrat = 1.0f; + } /* Add vertices and edge segments */ for (j = 0; j < edge_subd[i]; j++, v++, outedge++) { diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index e21410ad63d..3bef0ad6bf7 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -1677,8 +1677,18 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex /* Get overlap map. */ /* TODO: For a better performanse use KD-Tree. */ struct BVHTreeFromMesh treedata; - BVHTree *bvhtree = bvhtree_from_mesh_verts_ex( - &treedata, mvert, totvert, false, v_mask, v_mask_act, wmd->merge_dist / 2, 2, 6, 0, NULL); + BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata, + mvert, + totvert, + false, + v_mask, + v_mask_act, + wmd->merge_dist / 2, + 2, + 6, + 0, + NULL, + NULL); if (v_mask) { MEM_freeN(v_mask); diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c index 4b7bd964052..578262e9f17 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_material.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c @@ -45,9 +45,18 @@ static int node_shader_gpu_output_material(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - GPUNodeLink *outlink; + GPUNodeLink *outlink, *alpha_threshold_link; - GPU_stack_link(mat, node, "node_output_material", in, out, &outlink); + Material *ma = GPU_material_get_material(mat); + if (ma && ma->blend_method == MA_BM_CLIP) { + alpha_threshold_link = GPU_uniform(&ma->alpha_threshold); + } + else { + static float no_alpha_threshold = -1.0f; + alpha_threshold_link = GPU_uniform(&no_alpha_threshold); + } + + GPU_stack_link(mat, node, "node_output_material", in, out, alpha_threshold_link, &outlink); GPU_material_output_link(mat, outlink); return true; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c index fd4efb1b7ec..0cf4b51f307 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -19,6 +19,8 @@ #include "../node_shader_util.h" +#include "GPU_draw.h" + /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_tex_environment_in[] = { @@ -56,6 +58,10 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node_original = node->original ? node->original : node; NodeTexImage *tex_original = node_original->storage; ImageUser *iuser = &tex_original->iuser; + eGPUSamplerState sampler = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER; + if (GPU_get_mipmap()) { + sampler |= GPU_SAMPLER_MIPMAP; + } GPUNodeLink *outalpha; @@ -72,49 +78,41 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, /* Compute texture coordinate. */ if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) { - /* To fix pole issue we clamp the v coordinate. The clamp value depends on the filter size. */ - float clamp_size = (ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) ? 1.5 : 0.5; - GPU_link(mat, - "node_tex_environment_equirectangular", - in[0].link, - GPU_constant(&clamp_size), - GPU_image(mat, ima, iuser), - &in[0].link); + GPU_link(mat, "node_tex_environment_equirectangular", in[0].link, &in[0].link); + /* To fix pole issue we clamp the v coordinate. */ + sampler &= ~GPU_SAMPLER_REPEAT_T; + /* Force the highest mipmap and don't do anisotropic filtering. + * This is to fix the artifact caused by derivatives discontinuity. */ + sampler &= ~(GPU_SAMPLER_MIPMAP | GPU_SAMPLER_ANISO); } else { GPU_link(mat, "node_tex_environment_mirror_ball", in[0].link, &in[0].link); + /* Fix pole issue. */ + sampler &= ~GPU_SAMPLER_REPEAT; } - /* Sample texture with correct interpolation. */ + const char *gpufunc; + static const char *names[] = { + "node_tex_image_linear", + "node_tex_image_cubic", + }; + switch (tex->interpolation) { case SHD_INTERP_LINEAR: - /* Force the highest mipmap and don't do anisotropic filtering. - * This is to fix the artifact caused by derivatives discontinuity. */ - GPU_link(mat, - "node_tex_image_linear_no_mip", - in[0].link, - GPU_image(mat, ima, iuser), - &out[0].link, - &outalpha); + gpufunc = names[0]; break; case SHD_INTERP_CLOSEST: - GPU_link(mat, - "node_tex_image_nearest", - in[0].link, - GPU_image(mat, ima, iuser), - &out[0].link, - &outalpha); + sampler &= ~(GPU_SAMPLER_FILTER | GPU_SAMPLER_MIPMAP); + gpufunc = names[0]; break; default: - GPU_link(mat, - "node_tex_image_cubic", - in[0].link, - GPU_image(mat, ima, iuser), - &out[0].link, - &outalpha); + gpufunc = names[1]; break; } + /* Sample texture with correct interpolation. */ + GPU_link(mat, gpufunc, in[0].link, GPU_image(mat, ima, iuser, sampler), &out[0].link, &outalpha); + if (out[0].hasoutput) { if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) || IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) { diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c index bfef9341913..cbda72cd228 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c @@ -19,6 +19,8 @@ #include "../node_shader_util.h" +#include "GPU_draw.h" + /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_tex_image_in[] = { @@ -57,31 +59,6 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, GPUNodeStack *in, GPUNodeStack *out) { - static const char *names[] = { - "node_tex_image_linear", - "node_tex_image_nearest", - "node_tex_image_cubic", - "node_tex_image_smart", - }; - static const char *names_tiled[] = { - "node_tex_tile_linear", - "node_tex_tile_nearest", - "node_tex_tile_cubic", - "node_tex_tile_smart", - }; - static const char *names_box[] = { - "tex_box_sample_linear", - "tex_box_sample_nearest", - "tex_box_sample_cubic", - "tex_box_sample_smart", - }; - static const char *names_clip[] = { - "tex_clip_linear", - "tex_clip_nearest", - "tex_clip_cubic", - "tex_clip_smart", - }; - Image *ima = (Image *)node->id; NodeTexImage *tex = node->storage; @@ -91,26 +68,11 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, NodeTexImage *tex_original = node_original->storage; ImageUser *iuser = &tex_original->iuser; - const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX) ? names_box[tex->interpolation] : - names[tex->interpolation]; - bool do_texco_extend = (tex->extension != SHD_IMAGE_EXTENSION_REPEAT); - const bool do_texco_clip = (tex->extension == SHD_IMAGE_EXTENSION_CLIP); - - if (do_texco_extend && (tex->projection != SHD_PROJ_BOX) && - ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) { - gpu_node_name = "node_tex_image_cubic_extend"; - /* We do it inside the sampling function */ - do_texco_extend = false; - } - - GPUNodeLink *norm, *col1, *col2, *col3, *input_coords, *gpu_image; - GPUNodeLink *vnor, *ob_mat, *blend; - GPUNodeLink **texco = &in[0].link; - if (!ima) { return GPU_stack_link(mat, node, "node_tex_image_empty", in, out); } + GPUNodeLink **texco = &in[0].link; if (!*texco) { *texco = GPU_attribute(mat, CD_MTFACE, ""); node_shader_gpu_bump_tex_coord(mat, node, texco); @@ -118,88 +80,73 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, node_shader_gpu_tex_mapping(mat, node, in, out); + eGPUSamplerState sampler_state = 0; + + switch (tex->extension) { + case SHD_IMAGE_EXTENSION_REPEAT: + sampler_state |= GPU_SAMPLER_REPEAT; + break; + case SHD_IMAGE_EXTENSION_CLIP: + sampler_state |= GPU_SAMPLER_CLAMP_BORDER; + break; + default: + break; + } + + if (tex->interpolation != SHD_INTERP_CLOSEST) { + sampler_state |= GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER; + sampler_state |= GPU_get_mipmap() ? GPU_SAMPLER_MIPMAP : 0; + } + const bool use_cubic = ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART); + if (ima->source == IMA_SRC_TILED) { + const char *gpu_node_name = use_cubic ? "node_tex_tile_cubic" : "node_tex_tile_linear"; + GPUNodeLink *gpu_image = GPU_image_tiled(mat, ima, iuser, sampler_state); + GPUNodeLink *gpu_image_tile_mapping = GPU_image_tiled_mapping(mat, ima, iuser); /* UDIM tiles needs a samper2DArray and sampler1DArray for tile mapping. */ - GPU_stack_link(mat, - node, - names_tiled[tex->interpolation], - in, - out, - GPU_image_tiled(mat, ima, iuser), - GPU_image_tiled_mapping(mat, ima, iuser)); + GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image, gpu_image_tile_mapping); } else { + const char *gpu_node_name = use_cubic ? "node_tex_image_cubic" : "node_tex_image_linear"; + switch (tex->projection) { - case SHD_PROJ_FLAT: - if (do_texco_clip) { - /* This seems redundant, but is required to ensure the texco link - * is not freed by GPU_link, as it is still needed for GPU_stack_link. - * Intermediate links like this can only be used once and are then - * freed immediately, but if we make it the output link of a set_rgb - * node it will be kept and can be used multiple times. */ - GPU_link(mat, "set_rgb", *texco, texco); - GPU_link(mat, "set_rgb", *texco, &input_coords); - } - if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco); - } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser)); + case SHD_PROJ_FLAT: { + GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state); + GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image); break; - - case SHD_PROJ_BOX: - vnor = GPU_builtin(GPU_WORLD_NORMAL); - ob_mat = GPU_builtin(GPU_OBJECT_MATRIX); - blend = GPU_uniform(&tex->projection_blend); - gpu_image = GPU_image(mat, ima, iuser); - + } + case SHD_PROJ_BOX: { + gpu_node_name = use_cubic ? "tex_box_sample_cubic" : "tex_box_sample_linear"; + GPUNodeLink *wnor, *col1, *col2, *col3; + GPUNodeLink *vnor = GPU_builtin(GPU_WORLD_NORMAL); + GPUNodeLink *ob_mat = GPU_builtin(GPU_OBJECT_MATRIX); + GPUNodeLink *blend = GPU_uniform(&tex->projection_blend); + GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state); /* equivalent to normal_world_to_object */ - GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm); - { - /* See SHD_PROJ_FLAT for explanation. */ - GPU_link(mat, "set_rgb", *texco, texco); - GPU_link(mat, "set_rgb", *texco, &input_coords); - in[0].link = input_coords; - } - GPU_link( - mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3); - GPU_stack_link( - mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend); + GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &wnor); + GPU_link(mat, gpu_node_name, in[0].link, wnor, gpu_image, &col1, &col2, &col3); + GPU_link(mat, "tex_box_blend", wnor, col1, col2, col3, blend, &out[0].link, &out[1].link); break; - - case SHD_PROJ_SPHERE: + } + case SHD_PROJ_SPHERE: { + /* This projection is known to have a derivative discontinuity. + * Hide it by turning off mipmapping. */ + sampler_state &= ~GPU_SAMPLER_MIPMAP; + GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state); GPU_link(mat, "point_texco_remap_square", *texco, texco); GPU_link(mat, "point_map_to_sphere", *texco, texco); - if (do_texco_clip) { - /* See SHD_PROJ_FLAT for explanation. */ - GPU_link(mat, "set_rgb", *texco, texco); - GPU_link(mat, "set_rgb", *texco, &input_coords); - } - if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco); - } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser)); + GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image); break; - - case SHD_PROJ_TUBE: + } + case SHD_PROJ_TUBE: { + /* This projection is known to have a derivative discontinuity. + * Hide it by turning off mipmapping. */ + sampler_state &= ~GPU_SAMPLER_MIPMAP; + GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state); GPU_link(mat, "point_texco_remap_square", *texco, texco); GPU_link(mat, "point_map_to_tube", *texco, texco); - if (do_texco_clip) { - /* See SHD_PROJ_FLAT for explanation. */ - GPU_link(mat, "set_rgb", *texco, texco); - GPU_link(mat, "set_rgb", *texco, &input_coords); - } - if (do_texco_extend) { - GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco); - } - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser)); + GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image); break; - } - - if (tex->projection != SHD_PROJ_BOX) { - if (do_texco_clip) { - gpu_node_name = names_clip[tex->interpolation]; - in[0].link = input_coords; - GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser), out[0].link); } } } diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index 38a5629a2cc..165286c3661 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -78,7 +78,7 @@ static int bpygpu_uniform_location_get(GPUShader *shader, const char *name, const char *error_prefix) { - int uniform = GPU_shader_get_uniform_ensure(shader, name); + int uniform = GPU_shader_get_uniform(shader, name); if (uniform == -1) { PyErr_Format(PyExc_ValueError, "%s: uniform %.32s not found", error_prefix, name); @@ -524,7 +524,7 @@ PyDoc_STRVAR(bpygpu_shader_calc_format_doc, static PyObject *bpygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg)) { BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL); - GPU_vertformat_from_interface(&ret->fmt, GPU_shader_get_interface(self->shader)); + GPU_vertformat_from_shader(&ret->fmt, self->shader); return (PyObject *)ret; } diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 28498e116df..dde1d13477f 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -44,8 +44,16 @@ void bpy_app_generic_callback(struct Main *main, static PyTypeObject BlenderAppCbType; static PyStructSequence_Field app_cb_info_fields[] = { - {"frame_change_pre", "on frame change for playback and rendering (before)"}, - {"frame_change_post", "on frame change for playback and rendering (after)"}, + {"frame_change_pre", + "Called after frame change for playback and rendering, before any data is evaluated for the " + "new frame. This makes it possible to change data and relations (for example swap an object " + "to another mesh) for the new frame. Note that this handler is **not** to be used as 'before " + "the frame changes' event. The dependency graph is not available in this handler, as data " + "and relations may have been altered and the dependency graph has not yet been updated for " + "that."}, + {"frame_change_post", + "Called after frame change for playback and rendering, after the data has been evaluated " + "for the new frame."}, {"render_pre", "on render (before)"}, {"render_post", "on render (after)"}, {"render_write", "on writing a render frame (directly after the frame is written)"}, diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c index cc9f5746bba..f9bcb8943f4 100644 --- a/source/blender/python/intern/bpy_rna_callback.c +++ b/source/blender/python/intern/bpy_rna_callback.c @@ -324,10 +324,8 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args) return NULL; } - bContext *C = BPy_GetContext(); - struct wmWindowManager *wm = CTX_wm_manager(C); handle = WM_paint_cursor_activate( - wm, params.space_type, params.region_type, NULL, cb_wm_cursor_draw, (void *)args); + params.space_type, params.region_type, NULL, cb_wm_cursor_draw, (void *)args); } else if (RNA_struct_is_a(srna, &RNA_Space)) { const char *error_prefix = "Space.draw_handler_add"; @@ -424,9 +422,7 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar args, "OO!:WindowManager.draw_cursor_remove", &cls, &PyCapsule_Type, &py_handle)) { return NULL; } - bContext *C = BPy_GetContext(); - struct wmWindowManager *wm = CTX_wm_manager(C); - WM_paint_cursor_end(wm, handle); + WM_paint_cursor_end(handle); capsule_clear = true; } else if (RNA_struct_is_a(srna, &RNA_Space)) { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index ffa5bc15876..802780b37f1 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -106,6 +106,17 @@ void WM_reinit_gizmomap_all(struct Main *bmain); void WM_script_tag_reload(void); +bool WM_window_find_under_cursor(const wmWindowManager *wm, + const wmWindow *win_ignore, + const wmWindow *win, + const int mval[2], + wmWindow **r_win, + int r_mval[2]); +void WM_window_pixel_sample_read(const wmWindowManager *wm, + const wmWindow *win, + const int pos[2], + float r_col[3]); + uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, int r_size[2]); int WM_window_pixels_x(const struct wmWindow *win); @@ -198,14 +209,13 @@ void WM_cursor_grab_disable(struct wmWindow *win, const int mouse_ungrab_xy[2]); void WM_cursor_time(struct wmWindow *win, int nr); struct wmPaintCursor *WM_paint_cursor_activate( - struct wmWindowManager *wm, short space_type, short region_type, bool (*poll)(struct bContext *C), void (*draw)(struct bContext *C, int, int, void *customdata), void *customdata); -bool WM_paint_cursor_end(struct wmWindowManager *wm, struct wmPaintCursor *handle); +bool WM_paint_cursor_end(struct wmPaintCursor *handle); void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *region); void WM_cursor_warp(struct wmWindow *win, int x, int y); diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index 07d7ccf31db..2af68956923 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -150,7 +150,7 @@ void WM_cursor_set(wmWindow *win, int curs) } if (win->cursor == curs) { - return; /* Cursor is already set */ + return; /* Cursor is already set */ } win->cursor = curs; diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 4cc9f4ee7d1..fa12d6cf974 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -574,13 +574,13 @@ void wm_draw_region_blend(ARegion *region, int view, bool blend) alpha = 1.0f; } - glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), + glUniform1i(GPU_shader_get_uniform(shader, "image"), 0); + glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), rect_tex.xmin, rect_tex.ymin, rect_tex.xmax, rect_tex.ymax); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), + glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), rect_geo.xmin, rect_geo.ymin, rect_geo.xmax, diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e5f288b1963..53d6df915d6 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1,4 +1,4 @@ -/* +/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -4254,7 +4254,7 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g /* imperfect but probably usable... draw/enable drags to other windows */ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event) { - int mx = event->x, my = event->y; + int mval[2] = {event->x, event->y}; if (wm->windows.first == wm->windows.last) { return NULL; @@ -4263,7 +4263,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi /* in order to use window size and mouse position (pixels), we have to use a WM function */ /* check if outside, include top window bar... */ - if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) { + if (mval[0] < 0 || mval[1] < 0 || mval[0] > WM_window_pixels_x(win) || + mval[1] > WM_window_pixels_y(win) + 30) { wmWindow *owin; wmEventHandler *handler; @@ -4276,25 +4277,10 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi } } - /* to desktop space */ - mx += (int)(U.pixelsize * win->posx); - my += (int)(U.pixelsize * win->posy); - - /* check other windows to see if it has mouse inside */ - for (owin = wm->windows.first; owin; owin = owin->next) { - - if (owin != win) { - int posx = (int)(U.pixelsize * owin->posx); - int posy = (int)(U.pixelsize * owin->posy); - - if (mx - posx >= 0 && owin->posy >= 0 && mx - posx <= WM_window_pixels_x(owin) && - my - posy <= WM_window_pixels_y(owin)) { - event->x = mx - (int)(U.pixelsize * owin->posx); - event->y = my - (int)(U.pixelsize * owin->posy); - - return owin; - } - } + if (WM_window_find_under_cursor(wm, win, win, mval, &owin, mval)) { + event->x = mval[0]; + event->y = mval[1]; + return owin; } } return NULL; diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index cc81e4f2715..ed1b29d61ce 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -141,11 +141,37 @@ static void wm_history_file_free(RecentFile *recent); static void wm_history_file_update(void); static void wm_history_file_write(void); -/* To be able to read files without windows closing, opening, moving +/* -------------------------------------------------------------------- */ +/** \name Misc Utility Functions + * \{ */ + +void WM_file_tag_modified(void) +{ + wmWindowManager *wm = G_MAIN->wm.first; + if (wm->file_saved) { + wm->file_saved = 0; + /* notifier that data changed, for save-over warning or header */ + WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL); + } +} + +bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm) +{ + return !wm->file_saved || ED_image_should_save_modified(bmain); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Window Matching for File Reading + * \{ */ + +/** + * To be able to read files without windows closing, opening, moving * we try to prepare for worst case: * - active window gets active screen from file * - restoring the screens from non-active windows - * Best case is all screens match, in that case they get assigned to proper window + * Best case is all screens match, in that case they get assigned to proper window. */ static void wm_window_match_init(bContext *C, ListBase *wmlist) { @@ -355,6 +381,12 @@ static void wm_window_match_do(bContext *C, } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Preferences Initialization & Versioning + * \{ */ + /* in case UserDef was read, we re-initialize all, and do versioning */ static void wm_init_userdef(Main *bmain) { @@ -389,6 +421,15 @@ static void wm_init_userdef(Main *bmain) # define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */ #endif +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read Exotic File Formats + * + * Currently only supports '.blend' files, + * we could support registering other file formats and their loaders. + * \{ */ + /* intended to check for non-blender formats but for now it only reads blends */ static int wm_read_exotic(const char *name) { @@ -441,6 +482,12 @@ static int wm_read_exotic(const char *name) return retval; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read Blend-File Shared Utilities + * \{ */ + void WM_file_autoexec_init(const char *filepath) { if (G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) { @@ -486,6 +533,24 @@ void wm_file_read_report(bContext *C, Main *bmain) /** * Logic shared between #WM_file_read & #wm_homefile_read, + * call before loading a file. + * \note In the case of #WM_file_read the file may fail to load. + * Change here shouldn't cause user-visible changes in that case. + */ +static void wm_file_read_pre(bContext *C, bool use_data, bool UNUSED(use_userdef)) +{ + if (use_data) { + BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE); + BLI_timer_on_file_load(); + } + + /* Always do this as both startup and preferences may have loaded in many font's + * at a different zoom level to the file being loaded. */ + UI_view2d_zoom_cache_reset(); +} + +/** + * Logic shared between #WM_file_read & #wm_homefile_read, * updates to make after reading a file. */ static void wm_file_read_post(bContext *C, @@ -510,12 +575,16 @@ static void wm_file_read_post(bContext *C, if (is_startup_file) { /* possible python hasn't been initialized */ if (CTX_py_init_get(C)) { - if (reset_app_template) { + bool reset_all = use_userdef; + if (use_userdef || reset_app_template) { /* Only run when we have a template path found. */ if (BKE_appdir_app_template_any()) { BPY_execute_string( C, (const char *[]){"bl_app_template_utils", NULL}, "bl_app_template_utils.reset()"); + reset_all = true; } + } + if (reset_all) { /* sync addons, these may have changed from the defaults */ BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()"); } @@ -601,21 +670,27 @@ static void wm_file_read_post(bContext *C, } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read Main Blend-File API + * \{ */ + bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) { /* assume automated tasks with background, don't write recent file list */ const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0); bool success = false; + const bool use_data = true; + const bool use_userdef = false; + /* so we can get the error message */ errno = 0; WM_cursor_wait(1); - BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE); - BLI_timer_on_file_load(); - - UI_view2d_zoom_cache_reset(); + wm_file_read_pre(C, use_data, use_userdef); /* first try to append data from exotic file formats... */ /* it throws error box when file doesn't exist and returns -1 */ @@ -675,8 +750,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports) } } - const bool use_data = true; - const bool use_userdef = false; wm_file_read_post(C, false, false, use_data, use_userdef, false); } #if 0 @@ -746,6 +819,12 @@ const char *WM_init_state_app_template_get(void) return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read Startup & Preferences Blend-File API + * \{ */ + /** * Called on startup, (context entirely filled with NULLs) * or called for 'New File' both startup.blend and userpref.blend are checked. @@ -802,6 +881,23 @@ void wm_homefile_read(bContext *C, * or use app-template startup.blend which the user hasn't saved. */ bool is_factory_startup = true; + const char *app_template = NULL; + bool update_defaults = false; + + if (filepath_startup_override != NULL) { + /* pass */ + } + else if (app_template_override) { + /* This may be clearing the current template by setting to an empty string. */ + app_template = app_template_override; + } + else if (!use_factory_settings && U.app_template[0]) { + app_template = U.app_template; + } + + const bool reset_app_template = ((!app_template && U.app_template[0]) || + (app_template && !STREQ(app_template, U.app_template))); + /* options exclude eachother */ BLI_assert((use_factory_settings && filepath_startup_override) == 0); @@ -809,18 +905,30 @@ void wm_homefile_read(bContext *C, SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC); } - if (use_data) { - BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE); - BLI_timer_on_file_load(); + if (use_userdef || reset_app_template) { +#ifdef WITH_PYTHON + /* This only runs once Blender has already started. */ + if (CTX_py_init_get(C)) { + /* This is restored by 'wm_file_read_post', disable before loading any preferences + * so an add-on can read their own preferences when un-registering, + * and use new preferences if/when re-registering, see T67577. + * + * Note that this fits into 'wm_file_read_pre' function but gets messy + * since we need to know if 'reset_app_template' is true. */ + BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()"); + } +#endif /* WITH_PYTHON */ + } + + wm_file_read_pre(C, use_data, use_userdef); + if (use_data) { G.relbase_valid = 0; /* put aside screens to match with persistent windows later */ wm_window_match_init(C, &wmbase); } - UI_view2d_zoom_cache_reset(); - filepath_startup[0] = '\0'; filepath_userdef[0] = '\0'; app_template_system[0] = '\0'; @@ -861,28 +969,6 @@ void wm_homefile_read(bContext *C, } } - const char *app_template = NULL; - bool update_defaults = false; - bool reset_app_template = false; - - if (filepath_startup_override != NULL) { - /* pass */ - } - else if (app_template_override) { - /* This may be clearing the current template by setting to an empty string. */ - app_template = app_template_override; - } - else if (!use_factory_settings && U.app_template[0]) { - app_template = U.app_template; - } - - if ((!app_template && U.app_template[0]) || - (app_template && !STREQ(app_template, U.app_template))) { - /* Always load UI when switching to another template. */ - G.fileflags &= ~G_FILE_NO_UI; - reset_app_template = true; - } - if ((app_template != NULL) && (app_template[0] != '\0')) { if (!BKE_appdir_app_template_id_search( app_template, app_template_system, sizeof(app_template_system))) { @@ -1028,6 +1114,11 @@ void wm_homefile_read(bContext *C, * Screws up autosaves otherwise can remove this eventually, * only in a 2.53 and older, now its not written. */ G.fileflags &= ~G_FILE_RELATIVE_REMAP; + + if (reset_app_template) { + /* Always load UI when switching to another template. */ + G.fileflags &= ~G_FILE_NO_UI; + } } bmain = CTX_data_main(C); @@ -1035,7 +1126,6 @@ void wm_homefile_read(bContext *C, if (use_userdef) { /* check userdef before open window, keymaps etc */ wm_init_userdef(bmain); - reset_app_template = true; } if (use_data) { @@ -1070,7 +1160,7 @@ void wm_homefile_read(bContext *C, } /* -------------------------------------------------------------------- */ -/** \name WM History File API +/** \name Blend-File History API * \{ */ void wm_history_file_read(void) @@ -1199,7 +1289,7 @@ static void wm_history_file_update(void) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Save Main .blend File (internal) +/** \name Save Main Blend-File (internal) * \{ */ /* screen can be NULL */ @@ -1623,18 +1713,8 @@ void wm_open_init_use_scripts(wmOperator *op, bool use_prefs) /** \} */ -void WM_file_tag_modified(void) -{ - wmWindowManager *wm = G_MAIN->wm.first; - if (wm->file_saved) { - wm->file_saved = 0; - /* notifier that data changed, for save-over warning or header */ - WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL); - } -} - /* -------------------------------------------------------------------- */ -/** \name Preferences/startup save & load. +/** \name Startup File Save Operator * \{ */ /** @@ -1699,48 +1779,11 @@ void WM_OT_save_homefile(wmOperatorType *ot) ot->exec = wm_homefile_write_exec; } -static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) -{ - bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare"); - BLI_addtail(&U.autoexec_paths, path_cmp); - U.runtime.is_dirty = true; - return OPERATOR_FINISHED; -} - -void WM_OT_userpref_autoexec_path_add(wmOperatorType *ot) -{ - ot->name = "Add Autoexec Path"; - ot->idname = "WM_OT_userpref_autoexec_path_add"; - ot->description = "Add path to exclude from autoexecution"; - - ot->exec = wm_userpref_autoexec_add_exec; - - ot->flag = OPTYPE_INTERNAL; -} - -static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op) -{ - const int index = RNA_int_get(op->ptr, "index"); - bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index); - if (path_cmp) { - BLI_freelinkN(&U.autoexec_paths, path_cmp); - U.runtime.is_dirty = true; - } - return OPERATOR_FINISHED; -} - -void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot) -{ - ot->name = "Remove Autoexec Path"; - ot->idname = "WM_OT_userpref_autoexec_path_remove"; - ot->description = "Remove path to exclude from autoexecution"; - - ot->exec = wm_userpref_autoexec_remove_exec; - - ot->flag = OPTYPE_INTERNAL; +/** \} */ - RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000); -} +/* -------------------------------------------------------------------- */ +/** \name Write Preferences Operator + * \{ */ /* Only save the prefs block. operator entry */ static int wm_userpref_write_exec(bContext *C, wmOperator *op) @@ -1765,6 +1808,12 @@ void WM_OT_save_userpref(wmOperatorType *ot) ot->exec = wm_userpref_write_exec; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read Preferences Operator + * \{ */ + /** * When reading preferences, there are some exceptions for values which are reset. */ @@ -1828,10 +1877,6 @@ static void wm_userpref_update_when_changed(bContext *C, rna_struct_update_when_changed(C, bmain, &ptr_a, &ptr_b); -#ifdef WITH_PYTHON - BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()"); -#endif - WM_reinit_gizmomap_all(bmain); WM_keyconfig_reload(C); @@ -1897,6 +1942,12 @@ void WM_OT_read_factory_userpref(wmOperatorType *ot) ot->exec = wm_userpref_read_exec; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read File History Operator + * \{ */ + static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) { ED_file_read_bookmarks(); @@ -1917,6 +1968,14 @@ void WM_OT_read_history(wmOperatorType *ot) ot->flag = OPTYPE_INTERNAL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Read Startup & Preferences Operator + * + * Both #WM_OT_read_homefile & #WM_OT_read_factory_settings. + * \{ */ + static int wm_homefile_read_exec(bContext *C, wmOperator *op) { const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings")); @@ -2442,7 +2501,7 @@ void WM_OT_revert_mainfile(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Recover last session & auto-save. +/** \name Recover Last Session Operator * \{ */ void WM_recover_last_session(bContext *C, ReportList *reports) @@ -2486,6 +2545,12 @@ void WM_OT_recover_last_session(wmOperatorType *ot) ot->exec = wm_recover_last_session_exec; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Auto-Save Main .blend File Operator + * \{ */ + static int wm_recover_auto_save_exec(bContext *C, wmOperator *op) { char filepath[FILE_MAX]; @@ -2540,6 +2605,8 @@ void WM_OT_recover_auto_save(wmOperatorType *ot) /* -------------------------------------------------------------------- */ /** \name Save Main .blend File Operator + * + * Both #WM_OT_save_as_mainfile & #WM_OT_save_mainfile. * \{ */ static void wm_filepath_default(char *filepath) @@ -2766,7 +2833,7 @@ void WM_OT_save_mainfile(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Auto-execution of scripts warning popup +/** \name Auto Script Execution Warning Dialog * \{ */ static void wm_block_autorun_warning_ignore(bContext *C, void *arg_block, void *UNUSED(arg)) @@ -2968,8 +3035,11 @@ void wm_test_autorun_warning(bContext *C) } } -/* Close File Dialog - *************************************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Close File Dialog + * \{ */ static char save_images_when_file_is_closed = true; @@ -3235,9 +3305,4 @@ void wm_close_file_dialog(bContext *C, wmGenericCallback *post_action) } } -bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm) -{ - return !wm->file_saved || ED_image_should_save_modified(bmain); -} - /** \} */ diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 9aa401722b7..6b2a74138c9 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -365,7 +365,7 @@ static void draw_filled_lasso(wmGesture *gt) IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR); GPU_shader_bind(state.shader); GPU_shader_uniform_vector( - state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red); + state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red); immDrawPixelsTex(&state, rect.xmin, diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index fc3f0c87b69..001acc459c2 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -187,7 +187,7 @@ void WM_init_opengl(Main *bmain) GPU_init(); GPU_set_mipmap(bmain, true); GPU_set_linear_mipmap(true); - GPU_set_anisotropic(bmain, U.anisotropic_filter); + GPU_set_anisotropic(U.anisotropic_filter); GPU_pass_cache_init(); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 39811d67b9a..f99f47bc3ad 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -2059,13 +2059,14 @@ static void WM_OT_console_toggle(wmOperatorType *ot) * * \{ */ -wmPaintCursor *WM_paint_cursor_activate(wmWindowManager *wm, - short space_type, +wmPaintCursor *WM_paint_cursor_activate(short space_type, short region_type, bool (*poll)(bContext *C), wmPaintCursorDraw draw, void *customdata) { + wmWindowManager *wm = G_MAIN->wm.first; + wmPaintCursor *pc = MEM_callocN(sizeof(wmPaintCursor), "paint cursor"); BLI_addtail(&wm->paintcursors, pc); @@ -2080,11 +2081,10 @@ wmPaintCursor *WM_paint_cursor_activate(wmWindowManager *wm, return pc; } -bool WM_paint_cursor_end(wmWindowManager *wm, wmPaintCursor *handle) +bool WM_paint_cursor_end(wmPaintCursor *handle) { - wmPaintCursor *pc; - - for (pc = wm->paintcursors.first; pc; pc = pc->next) { + wmWindowManager *wm = G_MAIN->wm.first; + for (wmPaintCursor *pc = wm->paintcursors.first; pc; pc = pc->next) { if (pc == (wmPaintCursor *)handle) { BLI_remlink(&wm->paintcursors, pc); MEM_freeN(pc); @@ -2759,7 +2759,7 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve /* add radial control paint cursor */ rc->cursor = WM_paint_cursor_activate( - wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, op->type->poll, radial_control_paint_cursor, rc); + SPACE_TYPE_ANY, RGN_TYPE_ANY, op->type->poll, radial_control_paint_cursor, rc); WM_event_add_modal_handler(C, op); @@ -2793,7 +2793,7 @@ static void radial_control_cancel(bContext *C, wmOperator *op) ED_area_status_text(area, NULL); - WM_paint_cursor_end(wm, rc->cursor); + WM_paint_cursor_end(rc->cursor); /* restore original paint cursors */ wm->paintcursors = rc->orig_paintcursors; @@ -3778,8 +3778,6 @@ void wm_operatortypes_register(void) WM_operatortype_append(WM_OT_save_userpref); WM_operatortype_append(WM_OT_read_userpref); WM_operatortype_append(WM_OT_read_factory_userpref); - WM_operatortype_append(WM_OT_userpref_autoexec_path_add); - WM_operatortype_append(WM_OT_userpref_autoexec_path_remove); WM_operatortype_append(WM_OT_window_fullscreen_toggle); WM_operatortype_append(WM_OT_quit_blender); WM_operatortype_append(WM_OT_open_mainfile); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 02b50af0ac3..1ba22652157 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1984,6 +1984,90 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Find Window Utility + * + * \{ */ +static void wm_window_desktop_pos_get(const wmWindow *win, + const int screen_pos[2], + int r_desk_pos[2]) +{ + /* To desktop space. */ + r_desk_pos[0] = screen_pos[0] + (int)(U.pixelsize * win->posx); + r_desk_pos[1] = screen_pos[1] + (int)(U.pixelsize * win->posy); +} + +static void wm_window_screen_pos_get(const wmWindow *win, + const int desktop_pos[2], + int r_scr_pos[2]) +{ + /* To window space. */ + r_scr_pos[0] = desktop_pos[0] - (int)(U.pixelsize * win->posx); + r_scr_pos[1] = desktop_pos[1] - (int)(U.pixelsize * win->posy); +} + +bool WM_window_find_under_cursor(const wmWindowManager *wm, + const wmWindow *win_ignore, + const wmWindow *win, + const int mval[2], + wmWindow **r_win, + int r_mval[2]) +{ + int desk_pos[2]; + wm_window_desktop_pos_get(win, mval, desk_pos); + + /* TODO: This should follow the order of the activated windows. + * The current solution is imperfect but usable in most cases. */ + LISTBASE_FOREACH (wmWindow *, win_iter, &wm->windows) { + if (win_iter == win_ignore) { + continue; + } + + if (win_iter->windowstate == GHOST_kWindowStateMinimized) { + continue; + } + + int scr_pos[2]; + wm_window_screen_pos_get(win_iter, desk_pos, scr_pos); + + if (scr_pos[0] >= 0 && win_iter->posy >= 0 && scr_pos[0] <= WM_window_pixels_x(win_iter) && + scr_pos[1] <= WM_window_pixels_y(win_iter)) { + + *r_win = win_iter; + copy_v2_v2_int(r_mval, scr_pos); + return true; + } + } + + return false; +} + +void WM_window_pixel_sample_read(const wmWindowManager *wm, + const wmWindow *win, + const int pos[2], + float r_col[3]) +{ + bool setup_context = wm->windrawable != win; + + if (setup_context) { + GHOST_ActivateWindowDrawingContext(win->ghostwin); + GPU_context_active_set(win->gpuctx); + } + + glReadBuffer(GL_FRONT); + glReadPixels(pos[0], pos[1], 1, 1, GL_RGB, GL_FLOAT, r_col); + glReadBuffer(GL_BACK); + + if (setup_context) { + if (wm->windrawable) { + GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin); + GPU_context_active_set(wm->windrawable->gpuctx); + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Window Screen Shot Utility * * Include here since it can involve low level buffer switching. diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h index e081742b904..42eab35cdb9 100644 --- a/source/blender/windowmanager/wm_files.h +++ b/source/blender/windowmanager/wm_files.h @@ -45,8 +45,6 @@ void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action); bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm); void WM_OT_save_homefile(struct wmOperatorType *ot); -void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot); -void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot); void WM_OT_save_userpref(struct wmOperatorType *ot); void WM_OT_read_userpref(struct wmOperatorType *ot); void WM_OT_read_factory_userpref(struct wmOperatorType *ot); diff --git a/source/tools b/source/tools -Subproject 8a36c2833db48ed78c436ee19534ce5cf3b2eee +Subproject 5cf2fc3e5dc28025394b57d8743401295528f31 |