diff options
author | Bastien Montagne <b.mont29@gmail.com> | 2020-02-25 18:18:17 +0300 |
---|---|---|
committer | Bastien Montagne <b.mont29@gmail.com> | 2020-02-25 18:18:17 +0300 |
commit | 1ee9fa05b6f7f35f848cc6d229170cc9dd72a054 (patch) | |
tree | 75ced6e674cba73791d2ac86ff96f2ef617714c8 | |
parent | 79f09c6bf275999ee9d0163fd6b79e5e32a21f48 (diff) | |
parent | 6dd3e7d84da632402bab3ee136fc7d3b47b3b697 (diff) |
Merge branch 'master' into id-ensure-unique-memory-address
188 files changed, 4651 insertions, 2178 deletions
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 6294ab8bdd3..0553f615805 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -377,9 +377,7 @@ OCIO_FORCE_REBUILD=false OCIO_SKIP=false OPENEXR_VERSION="2.4.0" -OPENEXR_VERSION_MIN="2.0.1" -ILMBASE_VERSION="2.4.0" -ILMBASE_VERSION_MIN="2.3" +OPENEXR_VERSION_MIN="2.3" OPENEXR_FORCE_BUILD=false OPENEXR_FORCE_REBUILD=false OPENEXR_SKIP=false @@ -868,16 +866,15 @@ BOOST_SOURCE=( "http://sourceforge.net/projects/boost/files/boost/$BOOST_VERSION BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options" OCIO_USE_REPO=false -OCIO_SOURCE=( "https://github.com/imageworks/OpenColorIO/archive/v$OCIO_VERSION.tar.gz") +OCIO_SOURCE=( "https://github.com/AcademySoftwareFoundation/OpenColorIO/archive/v$OCIO_VERSION.tar.gz") #~ OCIO_SOURCE_REPO=( "https://github.com/imageworks/OpenColorIO.git" ) #~ OCIO_SOURCE_REPO_UID="6de971097c7f552300f669ed69ca0b6cf5a70843" OPENEXR_USE_REPO=false -#~ OPENEXR_SOURCE=( "https://github.com/openexr/openexr/releases/download/v$OPENEXR_VERSION/openexr-$OPENEXR_VERSION.tar.gz" ) +OPENEXR_SOURCE=( "https://github.com/AcademySoftwareFoundation/openexr/archive/v$OPENEXR_VERSION.tar.gz" ) +OPENEXR_SOURCE_REPO=( "https://github.com/AcademySoftwareFoundation/openexr.git" ) OPENEXR_SOURCE_REPO_UID="0ac2ea34c8f3134148a5df4052e40f155b76f6fb" -OPENEXR_SOURCE=( "https://github.com/openexr/openexr/archive/$OPENEXR_SOURCE_REPO_UID.tar.gz" ) -#~ OPENEXR_SOURCE_REPO=( "https://github.com/mont29/openexr.git" ) -ILMBASE_SOURCE=( "https://github.com/openexr/openexr/releases/download/v$ILMBASE_VERSION/ilmbase-$ILMBASE_VERSION.tar.gz" ) +#~ OPENEXR_SOURCE=( "https://github.com/openexr/openexr/archive/$OPENEXR_SOURCE_REPO_UID.tar.gz" ) OIIO_USE_REPO=false OIIO_SOURCE=( "https://github.com/OpenImageIO/oiio/archive/Release-$OIIO_VERSION.tar.gz" ) @@ -974,7 +971,7 @@ You may also want to build them yourself (optional ones are [between brackets]): * Boost $BOOST_VERSION_MIN (from $BOOST_SOURCE, modules: $BOOST_BUILD_MODULES). * [FFMpeg $FFMPEG_VERSION_MIN (needs libvorbis, libogg, libtheora, libx264, libmp3lame, libxvidcore, libvpx, ...)] (from $FFMPEG_SOURCE). * [OpenColorIO $OCIO_VERSION_MIN] (from $OCIO_SOURCE). - * ILMBase $ILMBASE_VERSION_MIN (from $ILMBASE_SOURCE). + * ILMBase $OPENEXR_VERSION_MIN (from $OPENEXR_SOURCE). * OpenEXR $OPENEXR_VERSION_MIN (from $OPENEXR_SOURCE). * OpenImageIO $OIIO_VERSION_MIN (from $OIIO_SOURCE). * [LLVM $LLVM_VERSION_MIN (with clang)] (from $LLVM_SOURCE, and $LLVM_CLANG_SOURCE). @@ -1201,10 +1198,15 @@ _init_python() { _inst_shortcut=$INST/python-$PYTHON_VERSION_MIN } +_update_deps_python() { + : +} + clean_Python() { clean_Numpy _init_python _clean + _update_deps_python } compile_Python() { @@ -1225,6 +1227,10 @@ compile_Python() { if [ ! -d $_inst ]; then INFO "Building Python-$PYTHON_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_python prepare_opt @@ -1256,6 +1262,7 @@ compile_Python() { cd $CWD INFO "Done compiling Python-$PYTHON_VERSION!" + _is_building=false else INFO "Own Python-$PYTHON_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-python option." @@ -1274,9 +1281,14 @@ _init_numpy() { _inst_shortcut=$_python/$_site/numpy } +_update_deps_numpy() { + : +} + clean_Numpy() { _init_numpy _clean + _update_deps_numpy } compile_Numpy() { @@ -1297,6 +1309,10 @@ compile_Numpy() { if [ ! -d $_inst ]; then INFO "Building Numpy-$NUMPY_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_numpy prepare_opt @@ -1325,6 +1341,7 @@ compile_Numpy() { cd $CWD INFO "Done compiling Numpy-$NUMPY_VERSION!" + _is_building=false else INFO "Own Numpy-$NUMPY_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-numpy option." @@ -1341,9 +1358,23 @@ _init_boost() { _inst_shortcut=$INST/boost } +_update_deps_boost() { + OIIO_FORCE_REBUILD=true + OSL_FORCE_REBUILD=true + OPENVDB_FORCE_REBUILD=true + ALEMBIC_FORCE_REBUILD=true + if [ "$_is_building" = true ]; then + OIIO_FORCE_BUILD=true + OSL_FORCE_BUILD=true + OPENVDB_FORCE_BUILD=true + ALEMBIC_FORCE_BUILD=true + fi +} + clean_Boost() { _init_boost _clean + _update_deps_boost } compile_Boost() { @@ -1365,14 +1396,10 @@ compile_Boost() { if [ ! -d $_inst ]; then INFO "Building Boost-$BOOST_VERSION" + _is_building=true # Rebuild dependencies as well! - OIIO_FORCE_BUILD=true - OIIO_FORCE_REBUILD=true - OSL_FORCE_BUILD=true - OSL_FORCE_REBUILD=true - OPENVDB_FORCE_BUILD=true - OPENVDB_FORCE_REBUILD=true + _update_deps_boost prepare_opt @@ -1402,6 +1429,7 @@ compile_Boost() { cd $CWD INFO "Done compiling Boost-$BOOST_VERSION!" + _is_building=false else INFO "Own Boost-$BOOST_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-boost option." @@ -1425,9 +1453,14 @@ _init_ocio() { _inst_shortcut=$INST/ocio } +_update_deps_ocio() { + : +} + clean_OCIO() { _init_ocio _clean + _update_deps_ocio } compile_OCIO() { @@ -1448,6 +1481,10 @@ compile_OCIO() { if [ ! -d $_inst ]; then INFO "Building OpenColorIO-$OCIO_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_ocio prepare_opt @@ -1520,6 +1557,7 @@ compile_OCIO() { cd $CWD INFO "Done compiling OpenColorIO-$OCIO_VERSION!" + _is_building=false else INFO "Own OpenColorIO-$OCIO_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-ocio option." @@ -1529,112 +1567,28 @@ compile_OCIO() { } # ---------------------------------------------------------------------------- -# Build ILMBase - -_init_ilmbase() { - _src=$SRC/ILMBase-$ILMBASE_VERSION - _git=false - _inst=$TMP/ilmbase-$ILMBASE_VERSION - _inst_shortcut=$TMP/ilmbase -} - -clean_ILMBASE() { - _init_ilmbase - _clean -} - -compile_ILMBASE() { - if [ "$NO_BUILD" = true ]; then - WARNING "--no-build enabled, ILMBase will not be compiled!" - return - fi - - # To be changed each time we make edits that would modify the compiled result! - ilmbase_magic=10 - _init_ilmbase - - # Clean install if needed! - magic_compile_check ilmbase-$ILMBASE_VERSION $ilmbase_magic - if [ $? -eq 1 -o "$OPENEXR_FORCE_REBUILD" = true ]; then - clean_ILMBASE - rm -rf $_openexr_inst - fi - - if [ ! -d $_openexr_inst ]; then - INFO "Building ILMBase-$ILMBASE_VERSION" - - # Rebuild dependencies as well! - OPENEXR_FORCE_BUILD=true - OPENEXR_FORCE_REBUILD=true - - prepare_opt - - if [ ! -d $_src ]; then - INFO "Downloading ILMBase-$ILMBASE_VERSION" - mkdir -p $SRC - download ILMBASE_SOURCE[@] $_src.tar.gz - - INFO "Unpacking ILMBase-$ILMBASE_VERSION" - tar -C $SRC --transform "s,(.*/?)ilmbase-[^/]*(.*),\1ILMBase-$ILMBASE_VERSION\2,x" -xf $_src.tar.gz - - fi - - cd $_src - # Always refresh the whole build! - if [ -d build ]; then - rm -rf build - fi - mkdir build - cd build - - cmake_d="-D CMAKE_BUILD_TYPE=Release" - cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst" - cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" - cmake_d="$cmake_d -D BUILD_SHARED_LIBS=ON" - cmake_d="$cmake_d -D NAMESPACE_VERSIONING=OFF" # VERY IMPORTANT!!! - - if file /bin/cp | grep -q '32-bit'; then - cflags="-fPIC -m32 -march=i686" - else - cflags="-fPIC" - fi - - cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" .. - - make -j$THREADS && make install - - make clean - - if [ -d $_inst ]; then - _create_inst_shortcut - else - ERROR "ILMBase-$ILMBASE_VERSION failed to compile, exiting" - exit 1 - fi - cd $CWD - INFO "Done compiling ILMBase-$ILMBASE_VERSION!" - else - INFO "Own ILMBase-$ILMBASE_VERSION is up to date, nothing to do!" - INFO "If you want to force rebuild of this lib (and openexr), use the --force-openexr option." - fi - - magic_compile_set ilmbase-$ILMBASE_VERSION $ilmbase_magic -} - -# ---------------------------------------------------------------------------- -# Build OpenEXR +# Build OpenEXR (and ILMBase). _init_openexr() { _src=$SRC/OpenEXR-$OPENEXR_VERSION - _git=true + _git=false _inst=$_openexr_inst _inst_shortcut=$INST/openexr } +_update_deps_openexr() { + OIIO_FORCE_REBUILD=true + ALEMBIC_FORCE_REBUILD=true + if [ "$_is_building" = true ]; then + OIIO_FORCE_BUILD=true + ALEMBIC_FORCE_BUILD=true + fi +} + clean_OPENEXR() { - clean_ILMBASE _init_openexr _clean + _update_deps_openexr } compile_OPENEXR() { @@ -1644,7 +1598,7 @@ compile_OPENEXR() { fi # To be changed each time we make edits that would modify the compiled result! - openexr_magic=14 + openexr_magic=15 # Clean install if needed! magic_compile_check openexr-$OPENEXR_VERSION $openexr_magic @@ -1653,17 +1607,15 @@ compile_OPENEXR() { fi _openexr_inst=$INST/openexr-$OPENEXR_VERSION - compile_ILMBASE PRINT "" - _ilmbase_inst=$_inst_shortcut _init_openexr if [ ! -d $_inst ]; then - INFO "Building OpenEXR-$OPENEXR_VERSION" + INFO "Building ILMBase-$OPENEXR_VERSION and OpenEXR-$OPENEXR_VERSION" + _is_building=true # Rebuild dependencies as well! - OIIO_FORCE_BUILD=true - OIIO_FORCE_REBUILD=true + _update_deps_openexr prepare_opt @@ -1688,9 +1640,9 @@ compile_OPENEXR() { git pull origin master git checkout $OPENEXR_SOURCE_REPO_UID git reset --hard - oiio_src_path="../OpenEXR" + openexr_src_path="../OpenEXR" else - oiio_src_path=".." + openexr_src_path=".." fi # Always refresh the whole build! @@ -1700,12 +1652,13 @@ compile_OPENEXR() { mkdir build cd build - cmake_d="-D CMAKE_BUILD_TYPE=Release" - cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst" - cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" - cmake_d="$cmake_d -D ILMBASE_PACKAGE_PREFIX=$_ilmbase_inst" + cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_openexr_inst" + cmake_d="$cmake_d -D CMAKE_INSTALL_DOCDIR=/dev/null" # Hack, there is no option to disable that currently... cmake_d="$cmake_d -D BUILD_SHARED_LIBS=ON" - cmake_d="$cmake_d -D NAMESPACE_VERSIONING=OFF" # VERY IMPORTANT!!! + cmake_d="$cmake_d -D BUILD_TESTING=OFF" + cmake_d="$cmake_d -D OPENEXR_BUILD_UTILS=OFF" + cmake_d="$cmake_d -D PYILMBASE_ENABLE=OFF" + cmake_d="$cmake_d -D OPENEXR_VIEWERS_ENABLE=OFF" if file /bin/cp | grep -q '32-bit'; then cflags="-fPIC -m32 -march=i686" @@ -1713,7 +1666,7 @@ compile_OPENEXR() { cflags="-fPIC" fi - cmake $cmake_d -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" $oiio_src_path + cmake $cmake_d -D CMAKE_BUILD_TYPE=Release -D CMAKE_CXX_FLAGS="$cflags" -D CMAKE_EXE_LINKER_FLAGS="-lgcc_s -lgcc" $openexr_src_path make -j$THREADS && make install @@ -1721,8 +1674,6 @@ compile_OPENEXR() { if [ -d $_inst ]; then _create_inst_shortcut - # Copy ilmbase files here (blender expects same dir for ilmbase and openexr :/). - cp -an $_ilmbase_inst/* $_inst_shortcut else ERROR "OpenEXR-$OPENEXR_VERSION failed to compile, exiting" exit 1 @@ -1732,6 +1683,7 @@ compile_OPENEXR() { cd $CWD INFO "Done compiling OpenEXR-$OPENEXR_VERSION!" + _is_building=false else INFO "Own OpenEXR-$OPENEXR_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-openexr option." @@ -1753,9 +1705,17 @@ _init_oiio() { _inst_shortcut=$INST/oiio } +_update_deps_oiio() { + OSL_FORCE_REBUILD=true + if [ "$_is_building" = true ]; then + OSL_FORCE_BUILD=true + fi +} + clean_OIIO() { _init_oiio _clean + _update_deps_oiio } compile_OIIO() { @@ -1776,10 +1736,10 @@ compile_OIIO() { if [ ! -d $_inst ]; then INFO "Building OpenImageIO-$OIIO_VERSION" + _is_building=true # Rebuild dependencies as well! - OSL_FORCE_BUILD=true - OSL_FORCE_REBUILD=true + _update_deps_oiio prepare_opt @@ -1877,6 +1837,7 @@ compile_OIIO() { cd $CWD INFO "Done compiling OpenImageIO-$OIIO_VERSION!" + _is_building=false else INFO "Own OpenImageIO-$OIIO_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-oiio option." @@ -1897,9 +1858,17 @@ _init_llvm() { _inst_shortcut=$INST/llvm } +_update_deps_llvm() { + OSL_FORCE_REBUILD=true + if [ "$_is_building" = true ]; then + OSL_FORCE_BUILD=true + fi +} + clean_LLVM() { _init_llvm _clean + _update_deps_llvm } compile_LLVM() { @@ -1920,10 +1889,10 @@ compile_LLVM() { if [ ! -d $_inst ]; then INFO "Building LLVM-$LLVM_VERSION (CLANG included!)" + _is_building=true # Rebuild dependencies as well! - OSL_FORCE_BUILD=true - OSL_FORCE_REBUILD=true + _update_deps_llvm prepare_opt @@ -1982,6 +1951,7 @@ compile_LLVM() { cd $CWD INFO "Done compiling LLVM-$LLVM_VERSION (CLANG included)!" + _is_building=false else INFO "Own LLVM-$LLVM_VERSION (CLANG included) is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-llvm option." @@ -1998,9 +1968,14 @@ _init_osl() { _inst_shortcut=$INST/osl } +_update_deps_osl() { + : +} + clean_OSL() { _init_osl _clean + _update_deps_osl } compile_OSL() { @@ -2022,6 +1997,10 @@ compile_OSL() { if [ ! -d $_inst ]; then INFO "Building OpenShadingLanguage-$OSL_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_osl prepare_opt @@ -2066,15 +2045,16 @@ compile_OSL() { cmake_d="$cmake_d -D USE_SIMD=sse2" cmake_d="$cmake_d -D USE_LLVM_BITCODE=OFF" cmake_d="$cmake_d -D USE_PARTIO=OFF" + cmake_d="$cmake_d -D OSL_BUILD_MATERIALX=OFF" + cmake_d="$cmake_d -D USE_QT=OFF" #~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION" if [ "$_with_built_openexr" = true ]; then INFO "ILMBASE_HOME=$INST/openexr" - cmake_d="$cmake_d -D ILMBASE_HOME=$INST/openexr" + cmake_d="$cmake_d -D OPENEXR_ROOT_DIR=$INST/openexr" + cmake_d="$cmake_d -D ILMBASE_ROOT_DIR=$INST/openexr" # XXX Temp workaround... sigh, ILMBase really messed the things up by defining their custom names ON by default :( - cmake_d="$cmake_d -D ILMBASE_CUSTOM=ON" - cmake_d="$cmake_d -D ILMBASE_CUSTOM_LIBRARIES='Half;Iex;Imath;IlmThread'" fi if [ -d $INST/boost ]; then @@ -2112,6 +2092,7 @@ compile_OSL() { cd $CWD INFO "Done compiling OpenShadingLanguage-$OSL_VERSION!" + _is_building=false else INFO "Own OpenShadingLanguage-$OSL_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-osl option." @@ -2130,9 +2111,14 @@ _init_osd() { _inst_shortcut=$INST/osd } +_update_deps_osd() { + : +} + clean_OSD() { _init_osd _clean + _update_deps_osd } compile_OSD() { @@ -2153,6 +2139,10 @@ compile_OSD() { if [ ! -d $_inst ]; then INFO "Building OpenSubdiv-$OSD_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_osd prepare_opt @@ -2211,6 +2201,7 @@ compile_OSD() { cd $CWD INFO "Done compiling OpenSubdiv-$OSD_VERSION!" + _is_building=false else INFO "Own OpenSubdiv-$OSD_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-osd option." @@ -2229,9 +2220,17 @@ _init_blosc() { _inst_shortcut=$INST/blosc } +_update_deps_blosc() { + OPENVDB_FORCE_REBUILD=true + if [ "$_is_building" = true ]; then + OPENVDB_FORCE_BUILD=true + fi +} + clean_BLOSC() { _init_blosc _clean + _update_deps_blosc } compile_BLOSC() { @@ -2253,10 +2252,10 @@ compile_BLOSC() { if [ ! -d $_inst ]; then INFO "Building Blosc-$OPENVDB_BLOSC_VERSION" + _is_building=true # Rebuild dependencies as well! - OPENVDB_FORCE_BUILD=true - OPENVDB_FORCE_REBUILD=true + _update_deps_blosc prepare_opt @@ -2298,6 +2297,7 @@ compile_BLOSC() { fi cd $CWD INFO "Done compiling Blosc-$OPENVDB_BLOSC_VERSION!" + _is_building=false else INFO "Own Blosc-$OPENVDB_BLOSC_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib (and openvdb), use the --force-openvdb option." @@ -2318,9 +2318,14 @@ _init_openvdb() { _inst_shortcut=$INST/openvdb } +_update_deps_openvdb() { + : +} + clean_OPENVDB() { _init_openvdb _clean + _update_deps_openvdb } compile_OPENVDB() { @@ -2344,6 +2349,10 @@ compile_OPENVDB() { if [ ! -d $_inst ]; then INFO "Building OpenVDB-$OPENVDB_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_openvdb prepare_opt @@ -2403,6 +2412,7 @@ compile_OPENVDB() { cd $CWD INFO "Done compiling OpenVDB-$OPENVDB_VERSION!" + _is_building=false else INFO "Own OpenVDB-$OPENVDB_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-openvdb option." @@ -2421,9 +2431,14 @@ _init_alembic() { _inst_shortcut=$INST/alembic } +_update_deps_alembic() { + : +} + clean_ALEMBIC() { _init_alembic _clean + _update_deps_alembic } compile_ALEMBIC() { @@ -2444,6 +2459,10 @@ compile_ALEMBIC() { if [ ! -d $_inst ]; then INFO "Building Alembic-$ALEMBIC_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_alembic prepare_opt @@ -2498,6 +2517,7 @@ compile_ALEMBIC() { cd $CWD INFO "Done compiling Alembic-$ALEMBIC_VERSION!" + _is_building=false else INFO "Own Alembic-$ALEMBIC_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-alembic option." @@ -2514,9 +2534,14 @@ _init_usd() { _inst_shortcut=$INST/usd } +_update_deps_usd() { + : +} + clean_USD() { _init_usd _clean + _update_deps_usd } compile_USD() { @@ -2537,6 +2562,10 @@ compile_USD() { if [ ! -d $_inst ]; then INFO "Building USD-$USD_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_usd prepare_opt @@ -2580,6 +2609,7 @@ compile_USD() { cd $CWD INFO "Done compiling USD-$USD_VERSION!" + _is_building=true else INFO "Own USD-$USD_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-usd option." @@ -2597,9 +2627,14 @@ _init_opencollada() { _inst_shortcut=$INST/opencollada } +_update_deps_collada() { + : +} + clean_OpenCOLLADA() { _init_opencollada _clean + _update_deps_collada } compile_OpenCOLLADA() { @@ -2620,6 +2655,10 @@ compile_OpenCOLLADA() { if [ ! -d $_inst ]; then INFO "Building OpenCOLLADA-$OPENCOLLADA_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_collada prepare_opt @@ -2675,6 +2714,7 @@ compile_OpenCOLLADA() { cd $CWD INFO "Done compiling OpenCOLLADA-$OPENCOLLADA_VERSION!" + _is_building=false else INFO "Own OpenCOLLADA-$OPENCOLLADA_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-opencollada option." @@ -2691,9 +2731,14 @@ _init_embree() { _inst_shortcut=$INST/embree } +_update_deps_embree() { + : +} + clean_Embree() { _init_embree _clean + _update_deps_embree } compile_Embree() { @@ -2714,6 +2759,10 @@ compile_Embree() { if [ ! -d $_inst ]; then INFO "Building Embree-$EMBREE_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_embree prepare_opt @@ -2772,6 +2821,7 @@ compile_Embree() { cd $CWD INFO "Done compiling Embree-$EMBREE_VERSION!" + _is_building=false else INFO "Own Embree-$EMBREE_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-embree option." @@ -2788,9 +2838,14 @@ _init_oidn() { _inst_shortcut=$INST/oidn } +_update_deps_oidn() { + : +} + clean_oidn() { _init_oidn _clean + _update_deps_oidn } compile_OIDN() { @@ -2811,6 +2866,10 @@ compile_OIDN() { if [ ! -d $_inst ]; then INFO "Building OpenImageDenoise-$OIDN_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_oidn prepare_opt @@ -2864,6 +2923,7 @@ compile_OIDN() { cd $CWD INFO "Done compiling OpenImageDenoise-$OIDN_VERSION!" + _is_building=false else INFO "Own OpenImageDenoise-$OIDN_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-oidn option." @@ -2881,9 +2941,14 @@ _init_ffmpeg() { _inst_shortcut=$INST/ffmpeg } +_update_deps_ffmpeg() { + : +} + clean_FFmpeg() { _init_ffmpeg _clean + _update_deps_ffmpeg } compile_FFmpeg() { @@ -2904,6 +2969,10 @@ compile_FFmpeg() { if [ ! -d $_inst ]; then INFO "Building ffmpeg-$FFMPEG_VERSION" + _is_building=true + + # Rebuild dependencies as well! + _update_deps_ffmpeg prepare_opt @@ -2982,6 +3051,7 @@ compile_FFmpeg() { cd $CWD INFO "Done compiling ffmpeg-$FFMPEG_VERSION!" + _is_building=false else INFO "Own ffmpeg-$FFMPEG_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-ffmpeg option." diff --git a/build_files/build_environment/patches/.gitattributes b/build_files/build_environment/patches/.gitattributes new file mode 100644 index 00000000000..beb2d800f5b --- /dev/null +++ b/build_files/build_environment/patches/.gitattributes @@ -0,0 +1,2 @@ +# Files contains mixed line endings, patch needs to preserve them to apply. +opencollada.diff binary diff --git a/build_files/build_environment/patches/opencollada.diff b/build_files/build_environment/patches/opencollada.diff index e7f563acaa1..cd4cc2c1652 100644 --- a/build_files/build_environment/patches/opencollada.diff +++ b/build_files/build_environment/patches/opencollada.diff @@ -3,19 +3,32 @@ index 95abbe2..4f14f30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -254,11 +254,11 @@ if(USE_STATIC_MSVC_RUNTIME) - endif() - - #adding PCRE --find_package(PCRE) -+#find_package(PCRE) - if (PCRE_FOUND) - message(STATUS "SUCCESSFUL: PCRE found") - else () # if pcre not found building its local copy from ./Externals -- if (WIN32 OR APPLE) -+ if (1) - message("WARNING: Native PCRE not found, taking PCRE from ./Externals") - add_definitions(-DPCRE_STATIC) - add_subdirectory(${EXTERNAL_LIBRARIES}/pcre) + endif()
+
+ #adding PCRE
+-find_package(PCRE)
++#find_package(PCRE)
+ if (PCRE_FOUND)
+ message(STATUS "SUCCESSFUL: PCRE found")
+ else () # if pcre not found building its local copy from ./Externals
+- if (WIN32 OR APPLE)
++ if (1)
+ message("WARNING: Native PCRE not found, taking PCRE from ./Externals")
+ add_definitions(-DPCRE_STATIC)
+ add_subdirectory(${EXTERNAL_LIBRARIES}/pcre)
+diff --git a/DAEValidator/CMakeLists.txt b/DAEValidator/CMakeLists.txt +index 03ad540..f7d05cf 100644 +--- a/DAEValidator/CMakeLists.txt ++++ b/DAEValidator/CMakeLists.txt +@@ -98,7 +98,7 @@ if (WIN32) + # C4710: 'function' : function not inlined + # C4711: function 'function' selected for inline expansion + # C4820: 'bytes' bytes padding added after construct 'member_name' +- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Wall /WX /wd4505 /wd4514 /wd4592 /wd4710 /wd4711 /wd4820") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Wall /wd4505 /wd4514 /wd4592 /wd4710 /wd4711 /wd4820") + else () + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror") + endif () diff --git a/DAEValidator/library/include/no_warning_begin b/DAEValidator/library/include/no_warning_begin index 7a69c32..defb315 100644 --- a/DAEValidator/library/include/no_warning_begin @@ -30,34 +43,8 @@ index 7a69c32..defb315 100644 # if defined(_MSC_VER) && defined(_DEBUG) # pragma warning(disable:4548) # endif -diff --git a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp -index 1f9a3ee..d151e9a 100644 ---- a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp -+++ b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp -@@ -1553,7 +1553,7 @@ namespace GeneratedSaxParser - #if defined(COLLADABU_OS_WIN) && !defined(__MINGW32__) - return _isnan( value ) ? true : false; - #else --#ifdef isnan -+#if defined(isnan) || defined(__APPLE__) - return isnan( value ); - #else - return std::isnan(value); -diff --git a/DAEValidator/CMakeLists.txt b/DAEValidator/CMakeLists.txt -index 03ad540f..f7d05cfb 100644 ---- a/DAEValidator/CMakeLists.txt -+++ b/DAEValidator/CMakeLists.txt -@@ -98,7 +98,7 @@ if (WIN32) - # C4710: 'function' : function not inlined - # C4711: function 'function' selected for inline expansion - # C4820: 'bytes' bytes padding added after construct 'member_name' -- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Wall /WX /wd4505 /wd4514 /wd4592 /wd4710 /wd4711 /wd4820") -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /Wall /wd4505 /wd4514 /wd4592 /wd4710 /wd4711 /wd4820") - else () - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Werror") - endif () diff --git a/DAEValidator/library/src/ArgumentParser.cpp b/DAEValidator/library/src/ArgumentParser.cpp -index 897e4dcf..98a69ff1 100644 +index 897e4dc..98a69ff 100644 --- a/DAEValidator/library/src/ArgumentParser.cpp +++ b/DAEValidator/library/src/ArgumentParser.cpp @@ -6,10 +6,10 @@ @@ -74,14 +61,28 @@ index 897e4dcf..98a69ff1 100644 #endif namespace opencollada -diff -Naur orig/Externals/LibXML/CMakeLists.txt external_opencollada/Externals/LibXML/CMakeLists.txt ---- orig/Externals/LibXML/CMakeLists.txt 2018-11-26 15:43:10 -0700 -+++ external_opencollada/Externals/LibXML/CMakeLists.txt 2020-01-21 14:15:04 -0700 -@@ -9,6 +9,7 @@ - -DLIBXML_SCHEMAS_ENABLED - -DLIBXML_XPATH_ENABLED - -DLIBXML_TREE_ENABLED -+ -DLIBXML_STATIC - ) - - if(USE_STATIC_MSVC_RUNTIME) +diff --git a/Externals/LibXML/CMakeLists.txt b/Externals/LibXML/CMakeLists.txt +index 40081e7..e1d1bfa 100644 +--- a/Externals/LibXML/CMakeLists.txt ++++ b/Externals/LibXML/CMakeLists.txt +@@ -9,6 +9,7 @@ add_definitions( + -DLIBXML_SCHEMAS_ENABLED
+ -DLIBXML_XPATH_ENABLED
+ -DLIBXML_TREE_ENABLED
++ -DLIBXML_STATIC
+ )
+
+ if(USE_STATIC_MSVC_RUNTIME)
+diff --git a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp +index 1f9a3ee..d151e9a 100644 +--- a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp ++++ b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp +@@ -1553,7 +1553,7 @@ namespace GeneratedSaxParser + #if defined(COLLADABU_OS_WIN) && !defined(__MINGW32__) + return _isnan( value ) ? true : false; + #else +-#ifdef isnan ++#if defined(isnan) || defined(__APPLE__) + return isnan( value ); + #else + return std::isnan(value); diff --git a/build_files/buildbot/codesign/archive_with_indicator.py b/build_files/buildbot/codesign/archive_with_indicator.py index d1af207df83..085026fcf98 100644 --- a/build_files/buildbot/codesign/archive_with_indicator.py +++ b/build_files/buildbot/codesign/archive_with_indicator.py @@ -70,8 +70,12 @@ class ArchiveWithIndicator: self.archive_filepath = self.base_dir / archive_name self.ready_indicator_filepath = self.base_dir / ready_indicator_name - def is_ready(self) -> bool: - """Check whether the archive is ready for access.""" + def is_ready_unsafe(self) -> bool: + """ + Check whether the archive is ready for access. + + No guarding about possible network failres is done here. + """ if not self.ready_indicator_filepath.exists(): return False @@ -105,6 +109,26 @@ class ArchiveWithIndicator: return True + def is_ready(self) -> bool: + """ + Check whether the archive is ready for access. + + Will tolerate possible network failures: if there is a network failure + or if there is still no proper permission on a file False is returned. + """ + + # There are some intermitten problem happening at a random which is + # translates to "OSError : [WinError 59] An unexpected network error occurred". + # Some reports suggests it might be due to lack of permissions to the file, + # which might be applicable in our case since it's possible that file is + # initially created with non-accessible permissions and gets chmod-ed + # after initial creation. + try: + return self.is_ready_unsafe() + except OSError as e: + print(f'Exception checking archive: {e}') + return False + def tag_ready(self) -> None: """ Tag the archive as ready by creating the corresponding indication file. diff --git a/build_files/buildbot/codesign/base_code_signer.py b/build_files/buildbot/codesign/base_code_signer.py index 0505905c6f4..2f86531a4d0 100644 --- a/build_files/buildbot/codesign/base_code_signer.py +++ b/build_files/buildbot/codesign/base_code_signer.py @@ -326,6 +326,9 @@ class BaseCodeSigner(metaclass=abc.ABCMeta): self.copy_signed_files_to_directory( unpacked_signed_files_dir, destination_dir) + logger_builder.info('Removing archive with signed files...') + self.signed_archive_info.clean() + ############################################################################ # Signing server side helpers. diff --git a/build_files/windows/detect_msvc_vswhere.cmd b/build_files/windows/detect_msvc_vswhere.cmd index a538e506b39..609375cee89 100644 --- a/build_files/windows/detect_msvc_vswhere.cmd +++ b/build_files/windows/detect_msvc_vswhere.cmd @@ -34,6 +34,9 @@ if "%VS_InstallDir%"=="" ( set VCVARS=%VS_InstallDir%\VC\Auxiliary\Build\vcvarsall.bat if exist "%VCVARS%" ( + if NOT "%verbose%" == "" ( + echo calling "%VCVARS%" %BUILD_ARCH% + ) call "%VCVARS%" %BUILD_ARCH% ) else ( if NOT "%verbose%" == "" ( @@ -43,6 +46,9 @@ if exist "%VCVARS%" ( ) rem try msbuild +if NOT "%verbose%" == "" ( + echo Testing for MSBuild +) msbuild /version > NUL if errorlevel 1 ( if NOT "%verbose%" == "" ( @@ -56,6 +62,9 @@ if NOT "%verbose%" == "" ( ) REM try the c++ compiler +if NOT "%verbose%" == "" ( + echo Testing for the C/C++ Compiler +) cl 2> NUL 1>&2 if errorlevel 1 ( if NOT "%verbose%" == "" ( diff --git a/extern/audaspace/include/devices/IDevice.h b/extern/audaspace/include/devices/IDevice.h index 92a85d900e2..b9414e7d187 100644 --- a/extern/audaspace/include/devices/IDevice.h +++ b/extern/audaspace/include/devices/IDevice.h @@ -37,10 +37,10 @@ class ISynchronizer; /** * @interface IDevice * The IDevice interface represents an output device for sound sources. - * Output devices may be several backends such as plattform independand like - * SDL or OpenAL or plattform specific like ALSA, but they may also be + * Output devices may be several backends such as platform independand like + * SDL or OpenAL or platform specific like ALSA, but they may also be * files, RAM buffers or other types of streams. - * \warning Thread safety must be insured so that no reader is beeing called + * \warning Thread safety must be insured so that no reader is being called * twice at the same time. */ class IDevice : public ILockable diff --git a/extern/audaspace/include/devices/IDeviceFactory.h b/extern/audaspace/include/devices/IDeviceFactory.h index 6a0f4537b13..7023cc058c5 100644 --- a/extern/audaspace/include/devices/IDeviceFactory.h +++ b/extern/audaspace/include/devices/IDeviceFactory.h @@ -35,6 +35,8 @@ AUD_NAMESPACE_BEGIN class AUD_API IDeviceFactory { public: + virtual ~IDeviceFactory() {} + /** * Opens an audio device for playback. * \exception Exception Thrown if the audio device cannot be opened. diff --git a/extern/audaspace/include/file/IFileInput.h b/extern/audaspace/include/file/IFileInput.h index bb016a88602..aec929e7639 100644 --- a/extern/audaspace/include/file/IFileInput.h +++ b/extern/audaspace/include/file/IFileInput.h @@ -40,6 +40,8 @@ class Buffer; class AUD_API IFileInput { public: + virtual ~IFileInput() {}; + /** * Creates a reader for a file to be read. * \param filename Path to the file to be read. diff --git a/extern/audaspace/src/fx/DynamicMusic.cpp b/extern/audaspace/src/fx/DynamicMusic.cpp index c682108378f..b8f5c975b3f 100644 --- a/extern/audaspace/src/fx/DynamicMusic.cpp +++ b/extern/audaspace/src/fx/DynamicMusic.cpp @@ -171,7 +171,7 @@ bool DynamicMusic::pause() bool DynamicMusic::seek(float position) { - bool result; + bool result = false; if(m_currentHandle != nullptr) { diff --git a/extern/mantaflow/preprocessed/fileio/ioutil.cpp b/extern/mantaflow/preprocessed/fileio/ioutil.cpp index 0bbbc7b6d11..e04633c5634 100644 --- a/extern/mantaflow/preprocessed/fileio/ioutil.cpp +++ b/extern/mantaflow/preprocessed/fileio/ioutil.cpp @@ -23,21 +23,36 @@ extern "C" { # include <zlib.h> } +# if defined(WIN32) || defined(_WIN32) +# include <windows.h> +# include <string> +# endif + +using namespace std; + namespace Manta { -//! helper to handle non ascii filenames correctly, mainly problematic on windows +# if defined(WIN32) || defined(_WIN32) +static wstring stringToWstring(const char *str) +{ + const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), NULL, 0); + wstring strWide(length_wc, 0); + MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), &strWide[0], length_wc); + return strWide; +} +# endif + void *safeGzopen(const char *filename, const char *mode) { gzFile gzfile; -# if 0 - UTF16_ENCODE(filename); - // gzopen_w() is supported since zlib v1.2.7 - gzfile = gzopen_w(filename_16, mode); - UTF16_UN_ENCODE(filename); +# if defined(WIN32) || defined(_WIN32) + wstring filenameWide = stringToWstring(filename); + gzfile = gzopen_w(filenameWide.c_str(), mode); # else gzfile = gzopen(filename, mode); # endif + return gzfile; } #endif diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h index 0e84563eae3..614bf2b91c4 100644 --- a/extern/mantaflow/preprocessed/gitinfo.h +++ b/extern/mantaflow/preprocessed/gitinfo.h @@ -1,3 +1,3 @@ -#define MANTA_GIT_VERSION "commit 7b9e0d841274c65dce911ec578bd0b4779971422" +#define MANTA_GIT_VERSION "commit ce000bcbd7004e6549ac2f118755fcdc1f679bc3" diff --git a/extern/mantaflow/preprocessed/grid.cpp b/extern/mantaflow/preprocessed/grid.cpp index c21d56d8879..f10052349d5 100644 --- a/extern/mantaflow/preprocessed/grid.cpp +++ b/extern/mantaflow/preprocessed/grid.cpp @@ -1244,15 +1244,67 @@ void PbRegister_gridMaxDiffVec3() } } +struct knCopyMacToVec3 : public KernelBase { + knCopyMacToVec3(MACGrid &source, Grid<Vec3> &target) + : KernelBase(&source, 0), source(source), target(target) + { + runMessage(); + run(); + } + inline void op(int i, int j, int k, MACGrid &source, Grid<Vec3> &target) const + { + target(i, j, k) = source(i, j, k); + } + inline MACGrid &getArg0() + { + return source; + } + typedef MACGrid type0; + inline Grid<Vec3> &getArg1() + { + return target; + } + typedef Grid<Vec3> type1; + void runMessage() + { + debMsg("Executing kernel knCopyMacToVec3 ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 0; j < _maxY; j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, source, target); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, source, target); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this); + } + MACGrid &source; + Grid<Vec3> ⌖ +}; // simple helper functions to copy (convert) mac to vec3 , and levelset to real grids // (are assumed to be the same for running the test cases - in general they're not!) void copyMacToVec3(MACGrid &source, Grid<Vec3> &target) { - FOR_IJK(target) - { - target(i, j, k) = source(i, j, k); - } + knCopyMacToVec3(source, target); } static PyObject *_W_3(PyObject *_self, PyObject *_linargs, PyObject *_kwds) { @@ -1323,10 +1375,14 @@ void PbRegister_convertMacToVec3() } } -//! vec3->mac grid conversion , but with full resampling -void resampleVec3ToMac(Grid<Vec3> &source, MACGrid &target) -{ - FOR_IJK_BND(target, 1) +struct knResampleVec3ToMac : public KernelBase { + knResampleVec3ToMac(Grid<Vec3> &source, MACGrid &target) + : KernelBase(&source, 1), source(source), target(target) + { + runMessage(); + run(); + } + inline void op(int i, int j, int k, Grid<Vec3> &source, MACGrid &target) const { target(i, j, k)[0] = 0.5 * (source(i - 1, j, k)[0] + source(i, j, k))[0]; target(i, j, k)[1] = 0.5 * (source(i, j - 1, k)[1] + source(i, j, k))[1]; @@ -1334,6 +1390,55 @@ void resampleVec3ToMac(Grid<Vec3> &source, MACGrid &target) target(i, j, k)[2] = 0.5 * (source(i, j, k - 1)[2] + source(i, j, k))[2]; } } + inline Grid<Vec3> &getArg0() + { + return source; + } + typedef Grid<Vec3> type0; + inline MACGrid &getArg1() + { + return target; + } + typedef MACGrid type1; + void runMessage() + { + debMsg("Executing kernel knResampleVec3ToMac ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 1; j < _maxY; j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, source, target); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, source, target); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this); + } + Grid<Vec3> &source; + MACGrid ⌖ +}; +//! vec3->mac grid conversion , but with full resampling + +void resampleVec3ToMac(Grid<Vec3> &source, MACGrid &target) +{ + knResampleVec3ToMac(source, target); } static PyObject *_W_5(PyObject *_self, PyObject *_linargs, PyObject *_kwds) { @@ -1367,13 +1472,66 @@ void PbRegister_resampleVec3ToMac() } } -//! mac->vec3 grid conversion , with full resampling -void resampleMacToVec3(MACGrid &source, Grid<Vec3> &target) -{ - FOR_IJK_BND(target, 1) +struct knResampleMacToVec3 : public KernelBase { + knResampleMacToVec3(MACGrid &source, Grid<Vec3> &target) + : KernelBase(&source, 1), source(source), target(target) + { + runMessage(); + run(); + } + inline void op(int i, int j, int k, MACGrid &source, Grid<Vec3> &target) const { target(i, j, k) = source.getCentered(i, j, k); } + inline MACGrid &getArg0() + { + return source; + } + typedef MACGrid type0; + inline Grid<Vec3> &getArg1() + { + return target; + } + typedef Grid<Vec3> type1; + void runMessage() + { + debMsg("Executing kernel knResampleMacToVec3 ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 1; j < _maxY; j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, source, target); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, source, target); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this); + } + MACGrid &source; + Grid<Vec3> ⌖ +}; +//! mac->vec3 grid conversion , with full resampling + +void resampleMacToVec3(MACGrid &source, Grid<Vec3> &target) +{ + knResampleMacToVec3(source, target); } static PyObject *_W_6(PyObject *_self, PyObject *_linargs, PyObject *_kwds) { @@ -1407,12 +1565,65 @@ void PbRegister_resampleMacToVec3() } } -void copyLevelsetToReal(LevelsetGrid &source, Grid<Real> &target) -{ - FOR_IJK(target) +struct knCopyLevelsetToReal : public KernelBase { + knCopyLevelsetToReal(LevelsetGrid &source, Grid<Real> &target) + : KernelBase(&source, 0), source(source), target(target) + { + runMessage(); + run(); + } + inline void op(int i, int j, int k, LevelsetGrid &source, Grid<Real> &target) const { target(i, j, k) = source(i, j, k); } + inline LevelsetGrid &getArg0() + { + return source; + } + typedef LevelsetGrid type0; + inline Grid<Real> &getArg1() + { + return target; + } + typedef Grid<Real> type1; + void runMessage() + { + debMsg("Executing kernel knCopyLevelsetToReal ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 0; j < _maxY; j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, source, target); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, source, target); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this); + } + LevelsetGrid &source; + Grid<Real> ⌖ +}; + +void copyLevelsetToReal(LevelsetGrid &source, Grid<Real> &target) +{ + knCopyLevelsetToReal(source, target); } static PyObject *_W_7(PyObject *_self, PyObject *_linargs, PyObject *_kwds) { @@ -1446,17 +1657,95 @@ void PbRegister_copyLevelsetToReal() } } -void copyVec3ToReal(Grid<Vec3> &source, - Grid<Real> &targetX, - Grid<Real> &targetY, - Grid<Real> &targetZ) -{ - FOR_IJK(source) +struct knCopyVec3ToReal : public KernelBase { + knCopyVec3ToReal(Grid<Vec3> &source, + Grid<Real> &targetX, + Grid<Real> &targetY, + Grid<Real> &targetZ) + : KernelBase(&source, 0), + source(source), + targetX(targetX), + targetY(targetY), + targetZ(targetZ) + { + runMessage(); + run(); + } + inline void op(int i, + int j, + int k, + Grid<Vec3> &source, + Grid<Real> &targetX, + Grid<Real> &targetY, + Grid<Real> &targetZ) const { targetX(i, j, k) = source(i, j, k).x; targetY(i, j, k) = source(i, j, k).y; targetZ(i, j, k) = source(i, j, k).z; } + inline Grid<Vec3> &getArg0() + { + return source; + } + typedef Grid<Vec3> type0; + inline Grid<Real> &getArg1() + { + return targetX; + } + typedef Grid<Real> type1; + inline Grid<Real> &getArg2() + { + return targetY; + } + typedef Grid<Real> type2; + inline Grid<Real> &getArg3() + { + return targetZ; + } + typedef Grid<Real> type3; + void runMessage() + { + debMsg("Executing kernel knCopyVec3ToReal ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 0; j < _maxY; j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, source, targetX, targetY, targetZ); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, source, targetX, targetY, targetZ); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this); + } + Grid<Vec3> &source; + Grid<Real> &targetX; + Grid<Real> &targetY; + Grid<Real> &targetZ; +}; + +void copyVec3ToReal(Grid<Vec3> &source, + Grid<Real> &targetX, + Grid<Real> &targetY, + Grid<Real> &targetZ) +{ + knCopyVec3ToReal(source, targetX, targetY, targetZ); } static PyObject *_W_8(PyObject *_self, PyObject *_linargs, PyObject *_kwds) { @@ -1492,17 +1781,95 @@ void PbRegister_copyVec3ToReal() } } -void copyRealToVec3(Grid<Real> &sourceX, - Grid<Real> &sourceY, - Grid<Real> &sourceZ, - Grid<Vec3> &target) -{ - FOR_IJK(target) +struct knCopyRealToVec3 : public KernelBase { + knCopyRealToVec3(Grid<Real> &sourceX, + Grid<Real> &sourceY, + Grid<Real> &sourceZ, + Grid<Vec3> &target) + : KernelBase(&sourceX, 0), + sourceX(sourceX), + sourceY(sourceY), + sourceZ(sourceZ), + target(target) + { + runMessage(); + run(); + } + inline void op(int i, + int j, + int k, + Grid<Real> &sourceX, + Grid<Real> &sourceY, + Grid<Real> &sourceZ, + Grid<Vec3> &target) const { target(i, j, k).x = sourceX(i, j, k); target(i, j, k).y = sourceY(i, j, k); target(i, j, k).z = sourceZ(i, j, k); } + inline Grid<Real> &getArg0() + { + return sourceX; + } + typedef Grid<Real> type0; + inline Grid<Real> &getArg1() + { + return sourceY; + } + typedef Grid<Real> type1; + inline Grid<Real> &getArg2() + { + return sourceZ; + } + typedef Grid<Real> type2; + inline Grid<Vec3> &getArg3() + { + return target; + } + typedef Grid<Vec3> type3; + void runMessage() + { + debMsg("Executing kernel knCopyRealToVec3 ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range<IndexInt> &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 0; j < _maxY; j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, sourceX, sourceY, sourceZ, target); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 0; i < _maxX; i++) + op(i, j, k, sourceX, sourceY, sourceZ, target); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range<IndexInt>(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range<IndexInt>(0, maxY), *this); + } + Grid<Real> &sourceX; + Grid<Real> &sourceY; + Grid<Real> &sourceZ; + Grid<Vec3> ⌖ +}; + +void copyRealToVec3(Grid<Real> &sourceX, + Grid<Real> &sourceY, + Grid<Real> &sourceZ, + Grid<Vec3> &target) +{ + knCopyRealToVec3(sourceX, sourceY, sourceZ, target); } static PyObject *_W_9(PyObject *_self, PyObject *_linargs, PyObject *_kwds) { diff --git a/extern/mantaflow/preprocessed/levelset.cpp b/extern/mantaflow/preprocessed/levelset.cpp index dcc10718d71..a6f9fb40f3f 100644 --- a/extern/mantaflow/preprocessed/levelset.cpp +++ b/extern/mantaflow/preprocessed/levelset.cpp @@ -773,9 +773,9 @@ void LevelsetGrid::createMesh(Mesh &mesh) Grid<int> edgeVY(mParent); Grid<int> edgeVZ(mParent); - for (int i = 0; i < mSize.x - 1; i++) + for (int k = 0; k < mSize.z - 1; k++) for (int j = 0; j < mSize.y - 1; j++) - for (int k = 0; k < mSize.z - 1; k++) { + for (int i = 0; i < mSize.x - 1; i++) { Real value[8] = {get(i, j, k), get(i + 1, j, k), get(i + 1, j + 1, k), diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index ee7ac7737c0..7917edf8c88 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -245,9 +245,6 @@ def list_render_passes(srl): if srl.use_pass_transmission_direct: yield ("TransDir", "RGB", 'COLOR') if srl.use_pass_transmission_indirect: yield ("TransInd", "RGB", 'COLOR') if srl.use_pass_transmission_color: yield ("TransCol", "RGB", 'COLOR') - if srl.use_pass_subsurface_direct: yield ("SubsurfaceDir", "RGB", 'COLOR') - if srl.use_pass_subsurface_indirect: yield ("SubsurfaceInd", "RGB", 'COLOR') - if srl.use_pass_subsurface_color: yield ("SubsurfaceCol", "RGB", 'COLOR') if srl.use_pass_emit: yield ("Emit", "RGB", 'COLOR') if srl.use_pass_environment: yield ("Env", "RGB", 'COLOR') @@ -284,8 +281,7 @@ def list_render_passes(srl): yield ("Denoising Intensity", "X", 'VALUE') clean_options = ("denoising_diffuse_direct", "denoising_diffuse_indirect", "denoising_glossy_direct", "denoising_glossy_indirect", - "denoising_transmission_direct", "denoising_transmission_indirect", - "denoising_subsurface_direct", "denoising_subsurface_indirect") + "denoising_transmission_direct", "denoising_transmission_indirect") if any(getattr(crl, option) for option in clean_options): yield ("Denoising Clean", "RGB", 'COLOR') diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 23ff1771995..d66a1f70c48 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -178,10 +178,6 @@ enum_view3d_shading_render_pass= ( ('TRANSMISSION_INDIRECT', "Transmission Indirect", "Show the Transmission Indirect render pass", 45), ('TRANSMISSION_COLOR', "Transmission Color", "Show the Transmission Color render pass", 46), - ('SUBSURFACE_DIRECT', "Subsurface Direct", "Show the Subsurface Direct render pass", 47), - ('SUBSURFACE_INDIRECT', "Subsurface Indirect", "Show the Subsurface Indirect render pass", 48), - ('SUBSURFACE_COLOR', "Subsurface Color", "Show the Subsurface Color render pass", 49), - ('VOLUME_DIRECT', "Volume Direct", "Show the Volume Direct render pass", 50), ('VOLUME_INDIRECT', "Volume Indirect", "Show the Volume Indirect render pass", 51), @@ -573,6 +569,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=64, subtype='PIXEL' ) + preview_denoising_start_sample: IntProperty( + name="Start Denoising", + description="Sample to start denoising the preview at", + min=0, max=(1 << 24), + default=1, + ) debug_reset_timeout: FloatProperty( name="Reset timeout", @@ -652,7 +654,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ('DIFFUSE', "Diffuse", ""), ('GLOSSY', "Glossy", ""), ('TRANSMISSION', "Transmission", ""), - ('SUBSURFACE', "Subsurface", ""), ), ) @@ -1346,16 +1347,6 @@ class CyclesRenderLayerSettings(bpy.types.PropertyGroup): description="Denoise the indirect transmission lighting", default=True, ) - denoising_subsurface_direct: BoolProperty( - name="Subsurface Direct", - description="Denoise the direct subsurface lighting", - default=True, - ) - denoising_subsurface_indirect: BoolProperty( - name="Subsurface Indirect", - description="Denoise the indirect subsurface lighting", - default=True, - ) denoising_strength: FloatProperty( name="Denoising Strength", description="Controls neighbor pixel weighting for the denoising filter (lower values preserve more detail, but aren't as smooth)", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index f23d141e3da..ed9e3a4c9cf 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -710,6 +710,11 @@ class CYCLES_RENDER_PT_performance_viewport(CyclesButtonsPanel, Panel): col.prop(rd, "preview_pixel_size", text="Pixel Size") col.prop(cscene, "preview_start_resolution", text="Start Pixels") + if show_optix_denoising(context): + sub = col.row(align=True) + sub.active = cscene.preview_denoising != 'NONE' + sub.prop(cscene, "preview_denoising_start_sample", text="Denoising Start Sample") + class CYCLES_RENDER_PT_filter(CyclesButtonsPanel, Panel): bl_label = "Filter" @@ -853,14 +858,6 @@ class CYCLES_RENDER_PT_passes_light(CyclesButtonsPanel, Panel): split = layout.split(factor=0.35) split.use_property_split = False - split.label(text="Subsurface") - row = split.row(align=True) - row.prop(view_layer, "use_pass_subsurface_direct", text="Direct", toggle=True) - row.prop(view_layer, "use_pass_subsurface_indirect", text="Indirect", toggle=True) - row.prop(view_layer, "use_pass_subsurface_color", text="Color", toggle=True) - - split = layout.split(factor=0.35) - split.use_property_split = False split.label(text="Volume") row = split.row(align=True) row.prop(cycles_view_layer, "use_pass_volume_direct", text="Direct", toggle=True) @@ -1040,15 +1037,6 @@ class CYCLES_RENDER_PT_denoising(CyclesButtonsPanel, Panel): split = layout.split(factor=0.5) split.active = cycles_view_layer.use_denoising or cycles_view_layer.denoising_store_passes - col = split.column() - col.alignment = 'RIGHT' - col.label(text="Subsurface") - - row = split.row(align=True) - row.use_property_split = False - row.prop(cycles_view_layer, "denoising_subsurface_direct", text="Direct", toggle=True) - row.prop(cycles_view_layer, "denoising_subsurface_indirect", text="Indirect", toggle=True) - class CYCLES_PT_post_processing(CyclesButtonsPanel, Panel): bl_label = "Post Processing" @@ -1856,7 +1844,7 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel): cscene = scene.cycles rd = scene.render if rd.use_bake_multires == False and cscene.bake_type in { - 'NORMAL', 'COMBINED', 'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}: + 'NORMAL', 'COMBINED', 'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}: return True def draw(self, context): @@ -1895,7 +1883,7 @@ class CYCLES_RENDER_PT_bake_influence(CyclesButtonsPanel, Panel): flow.prop(cbk, "use_pass_ambient_occlusion") flow.prop(cbk, "use_pass_emit") - elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}: + elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION'}: row = col.row(align=True) row.use_property_split = False row.prop(cbk, "use_pass_direct", toggle=True) diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index 899245db03e..49f23f4ba30 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -42,10 +42,7 @@ def custom_bake_remap(scene): 'GLOSSY_COLOR', 'TRANSMISSION_DIRECT', 'TRANSMISSION_INDIRECT', - 'TRANSMISSION_COLOR', - 'SUBSURFACE_DIRECT', - 'SUBSURFACE_INDIRECT', - 'SUBSURFACE_COLOR') + 'TRANSMISSION_COLOR') diffuse_direct_idx = bake_lookup.index('DIFFUSE_DIRECT') diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index affd5685337..fe0f8f3b88a 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -1154,7 +1154,10 @@ void BlenderSync::sync_particle_hair( } } -void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry *geom) +void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, + BL::Object b_ob, + Geometry *geom, + const vector<Shader *> &used_shaders) { Hair *hair = (geom->type == Geometry::HAIR) ? static_cast<Hair *>(geom) : NULL; Mesh *mesh = (geom->type == Geometry::MESH) ? static_cast<Mesh *>(geom) : NULL; @@ -1172,6 +1175,9 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry oldtriangles.steal_data(mesh->triangles); } + geom->clear(); + geom->used_shaders = used_shaders; + if (view_layer.use_hair && scene->curve_system_manager->use_curves) { /* Particle hair. */ bool need_undeformed = geom->need_attribute(scene, ATTR_STD_GENERATED); diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp index c3c307318a8..d0f8465a98f 100644 --- a/intern/cycles/blender/blender_device.cpp +++ b/intern/cycles/blender/blender_device.cpp @@ -115,8 +115,9 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen } /* Ensure there is an OptiX device when using the OptiX denoiser. */ - bool use_optix_denoising = DENOISER_OPTIX == - get_enum(cscene, "preview_denoising", DENOISER_NUM, DENOISER_NONE); + bool use_optix_denoising = get_enum(cscene, "preview_denoising", DENOISER_NUM, DENOISER_NONE) == + DENOISER_OPTIX && + !background; BL::Scene::view_layers_iterator b_view_layer; for (b_scene.view_layers.begin(b_view_layer); b_view_layer != b_scene.view_layers.end(); ++b_view_layer) { diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp index 8b803835b62..304b3d18e27 100644 --- a/intern/cycles/blender/blender_geometry.cpp +++ b/intern/cycles/blender/blender_geometry.cpp @@ -117,20 +117,18 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, geometry_synced.insert(geom); - geom->clear(); - geom->used_shaders = used_shaders; geom->name = ustring(b_ob_data.name().c_str()); if (use_particle_hair) { - sync_hair(b_depsgraph, b_ob, geom); + sync_hair(b_depsgraph, b_ob, geom, used_shaders); } else if (object_fluid_gas_domain_find(b_ob)) { Mesh *mesh = static_cast<Mesh *>(geom); - sync_volume(b_ob, mesh); + sync_volume(b_ob, mesh, used_shaders); } else { Mesh *mesh = static_cast<Mesh *>(geom); - sync_mesh(b_depsgraph, b_ob, mesh); + sync_mesh(b_depsgraph, b_ob, mesh, used_shaders); } return geom; diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 42300f6eb6f..075c9250e8c 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -941,7 +941,10 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) } } -void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh) +void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, + BL::Object b_ob, + Mesh *mesh, + const vector<Shader *> &used_shaders) { array<int> oldtriangles; array<Mesh::SubdFace> oldsubd_faces; @@ -950,6 +953,9 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me oldsubd_faces.steal_data(mesh->subd_faces); oldsubd_face_corners.steal_data(mesh->subd_face_corners); + mesh->clear(); + mesh->used_shaders = used_shaders; + mesh->subdivision_type = Mesh::SUBDIVISION_NONE; if (view_layer.use_surfaces) { diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 2e7a72d8072..5cfb1200c7c 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -278,8 +278,6 @@ static ShaderEvalType get_shader_type(const string &pass_type) return SHADER_EVAL_GLOSSY_COLOR; else if (strcmp(shader_type, "TRANSMISSION_COLOR") == 0) return SHADER_EVAL_TRANSMISSION_COLOR; - else if (strcmp(shader_type, "SUBSURFACE_COLOR") == 0) - return SHADER_EVAL_SUBSURFACE_COLOR; else if (strcmp(shader_type, "EMIT") == 0) return SHADER_EVAL_EMISSION; @@ -296,8 +294,6 @@ static ShaderEvalType get_shader_type(const string &pass_type) return SHADER_EVAL_GLOSSY; else if (strcmp(shader_type, "TRANSMISSION") == 0) return SHADER_EVAL_TRANSMISSION; - else if (strcmp(shader_type, "SUBSURFACE") == 0) - return SHADER_EVAL_SUBSURFACE; /* extra */ else if (strcmp(shader_type, "ENVIRONMENT") == 0) @@ -640,8 +636,6 @@ static int bake_pass_filter_get(const int pass_filter) flag |= BAKE_FILTER_GLOSSY; if ((pass_filter & BL::BakeSettings::pass_filter_TRANSMISSION) != 0) flag |= BAKE_FILTER_TRANSMISSION; - if ((pass_filter & BL::BakeSettings::pass_filter_SUBSURFACE) != 0) - flag |= BAKE_FILTER_SUBSURFACE; if ((pass_filter & BL::BakeSettings::pass_filter_EMIT) != 0) flag |= BAKE_FILTER_EMISSION; @@ -855,6 +849,7 @@ void BlenderSession::synchronize(BL::Depsgraph &b_depsgraph_) /* increase samples, but never decrease */ session->set_samples(session_params.samples); + session->set_denoising_start_sample(session_params.denoising_start_sample); session->set_pause(session_pause); /* copy recalc flags, outside of mutex so we can decide to do the real diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 0412654d3bd..50442c6ebdc 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -461,19 +461,16 @@ PassType BlenderSync::get_pass_type(BL::RenderPass &b_pass) MAP_PASS("DiffDir", PASS_DIFFUSE_DIRECT); MAP_PASS("GlossDir", PASS_GLOSSY_DIRECT); MAP_PASS("TransDir", PASS_TRANSMISSION_DIRECT); - MAP_PASS("SubsurfaceDir", PASS_SUBSURFACE_DIRECT); MAP_PASS("VolumeDir", PASS_VOLUME_DIRECT); MAP_PASS("DiffInd", PASS_DIFFUSE_INDIRECT); MAP_PASS("GlossInd", PASS_GLOSSY_INDIRECT); MAP_PASS("TransInd", PASS_TRANSMISSION_INDIRECT); - MAP_PASS("SubsurfaceInd", PASS_SUBSURFACE_INDIRECT); MAP_PASS("VolumeInd", PASS_VOLUME_INDIRECT); MAP_PASS("DiffCol", PASS_DIFFUSE_COLOR); MAP_PASS("GlossCol", PASS_GLOSSY_COLOR); MAP_PASS("TransCol", PASS_TRANSMISSION_COLOR); - MAP_PASS("SubsurfaceCol", PASS_SUBSURFACE_COLOR); MAP_PASS("Emit", PASS_EMISSION); MAP_PASS("Env", PASS_BACKGROUND); @@ -556,8 +553,6 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLa MAP_OPTION("denoising_glossy_indirect", DENOISING_CLEAN_GLOSSY_IND); MAP_OPTION("denoising_transmission_direct", DENOISING_CLEAN_TRANSMISSION_DIR); MAP_OPTION("denoising_transmission_indirect", DENOISING_CLEAN_TRANSMISSION_IND); - MAP_OPTION("denoising_subsurface_direct", DENOISING_CLEAN_SUBSURFACE_DIR); - MAP_OPTION("denoising_subsurface_indirect", DENOISING_CLEAN_SUBSURFACE_IND); #undef MAP_OPTION } b_engine.add_pass("Noisy Image", 4, "RGBA", b_view_layer.name().c_str()); @@ -837,6 +832,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine, /* other parameters */ params.start_resolution = get_int(cscene, "preview_start_resolution"); + params.denoising_start_sample = get_int(cscene, "preview_denoising_start_sample"); params.pixel_size = b_engine.get_preview_pixel_size(b_scene); /* other parameters */ diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index efd4511eb1e..219a3615835 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -137,14 +137,20 @@ class BlenderSync { bool *use_portal); /* Volume */ - void sync_volume(BL::Object &b_ob, Mesh *mesh); + void sync_volume(BL::Object &b_ob, Mesh *mesh, const vector<Shader *> &used_shaders); /* Mesh */ - void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh); + void sync_mesh(BL::Depsgraph b_depsgraph, + BL::Object b_ob, + Mesh *mesh, + const vector<Shader *> &used_shaders); void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step); /* Hair */ - void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry *geom); + void sync_hair(BL::Depsgraph b_depsgraph, + BL::Object b_ob, + Geometry *geom, + const vector<Shader *> &used_shaders); void sync_hair_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Geometry *geom, diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index 87fb9620725..ae70e60d60e 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -80,10 +80,13 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float } } -void BlenderSync::sync_volume(BL::Object &b_ob, Mesh *mesh) +void BlenderSync::sync_volume(BL::Object &b_ob, Mesh *mesh, const vector<Shader *> &used_shaders) { bool old_has_voxel_attributes = mesh->has_voxel_attributes(); + mesh->clear(); + mesh->used_shaders = used_shaders; + /* Smoke domain. */ sync_smoke_volume(scene, b_ob, mesh, b_scene.frame_current()); diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index 84b00aab91c..639dfe3cee2 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -727,6 +727,12 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair num_keys += c.num_keys; } + /* Catmull-Rom splines need extra CVs at the beginning and end of each curve. */ + size_t num_keys_embree = num_keys; + if (use_curves) { + num_keys_embree += num_curves * 2; + } + /* Copy the CV data to Embree */ const int t_mid = (num_motion_steps - 1) / 2; const float *curve_radius = &hair->curve_radius[0]; @@ -741,42 +747,28 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair } float4 *rtc_verts = (float4 *)rtcSetNewGeometryBuffer( - geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, sizeof(float) * 4, num_keys); - float4 *rtc_tangents = NULL; - if (use_curves) { - rtc_tangents = (float4 *)rtcSetNewGeometryBuffer( - geom_id, RTC_BUFFER_TYPE_TANGENT, t, RTC_FORMAT_FLOAT4, sizeof(float) * 4, num_keys); - assert(rtc_tangents); - } + geom_id, RTC_BUFFER_TYPE_VERTEX, t, RTC_FORMAT_FLOAT4, sizeof(float) * 4, num_keys_embree); + assert(rtc_verts); if (rtc_verts) { - if (use_curves && rtc_tangents) { + if (use_curves) { const size_t num_curves = hair->num_curves(); for (size_t j = 0; j < num_curves; ++j) { Hair::Curve c = hair->get_curve(j); int fk = c.first_key; - rtc_verts[0] = float3_to_float4(verts[fk]); - rtc_verts[0].w = curve_radius[fk]; - rtc_tangents[0] = float3_to_float4(verts[fk + 1] - verts[fk]); - rtc_tangents[0].w = curve_radius[fk + 1] - curve_radius[fk]; - ++fk; int k = 1; - for (; k < c.num_segments(); ++k, ++fk) { + for (; k < c.num_keys + 1; ++k, ++fk) { rtc_verts[k] = float3_to_float4(verts[fk]); rtc_verts[k].w = curve_radius[fk]; - rtc_tangents[k] = float3_to_float4((verts[fk + 1] - verts[fk - 1]) * 0.5f); - rtc_tangents[k].w = (curve_radius[fk + 1] - curve_radius[fk - 1]) * 0.5f; } - rtc_verts[k] = float3_to_float4(verts[fk]); - rtc_verts[k].w = curve_radius[fk]; - rtc_tangents[k] = float3_to_float4(verts[fk] - verts[fk - 1]); - rtc_tangents[k].w = curve_radius[fk] - curve_radius[fk - 1]; - rtc_verts += c.num_keys; - rtc_tangents += c.num_keys; + /* Duplicate Embree's Catmull-Rom spline CVs at the start and end of each curve. */ + rtc_verts[0] = rtc_verts[1]; + rtc_verts[k] = rtc_verts[k - 1]; + rtc_verts += c.num_keys + 2; } } else { - for (size_t j = 0; j < num_keys; ++j) { + for (size_t j = 0; j < num_keys_embree; ++j) { rtc_verts[j] = float3_to_float4(verts[j]); rtc_verts[j].w = curve_radius[j]; } @@ -820,8 +812,8 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) enum RTCGeometryType type = (!use_curves) ? RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE : - (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE : - RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE); + (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : + RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type); rtcSetGeometryTessellationRate(geom_id, curve_subdivisions); @@ -832,6 +824,10 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) Hair::Curve c = hair->get_curve(j); for (size_t k = 0; k < c.num_segments(); ++k) { rtc_indices[rtc_index] = c.first_key + k; + if (use_curves) { + /* Room for extra CVs at Catmull-Rom splines. */ + rtc_indices[rtc_index] += j * 2; + } /* Cycles specific data. */ pack.prim_object[prim_object_size + rtc_index] = i; pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT( diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h index 9ea75d54c5d..79ea03f4f6f 100644 --- a/intern/cycles/kernel/kernel_accumulate.h +++ b/intern/cycles/kernel/kernel_accumulate.h @@ -36,21 +36,18 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, eval->glossy = make_float3(0.0f, 0.0f, 0.0f); eval->transmission = make_float3(0.0f, 0.0f, 0.0f); eval->transparent = make_float3(0.0f, 0.0f, 0.0f); - eval->subsurface = make_float3(0.0f, 0.0f, 0.0f); - eval->scatter = make_float3(0.0f, 0.0f, 0.0f); + eval->volume = make_float3(0.0f, 0.0f, 0.0f); if (type == CLOSURE_BSDF_TRANSPARENT_ID) eval->transparent = value; - else if (CLOSURE_IS_BSDF_DIFFUSE(type)) + else if (CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_BSDF_BSSRDF(type)) eval->diffuse = value; else if (CLOSURE_IS_BSDF_GLOSSY(type)) eval->glossy = value; else if (CLOSURE_IS_BSDF_TRANSMISSION(type)) eval->transmission = value; - else if (CLOSURE_IS_BSDF_BSSRDF(type)) - eval->subsurface = value; else if (CLOSURE_IS_PHASE(type)) - eval->scatter = value; + eval->volume = value; } else #endif @@ -73,16 +70,14 @@ ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, value *= mis_weight; #ifdef __PASSES__ if (eval->use_light_pass) { - if (CLOSURE_IS_BSDF_DIFFUSE(type)) + if (CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_BSDF_BSSRDF(type)) eval->diffuse += value; else if (CLOSURE_IS_BSDF_GLOSSY(type)) eval->glossy += value; else if (CLOSURE_IS_BSDF_TRANSMISSION(type)) eval->transmission += value; - else if (CLOSURE_IS_BSDF_BSSRDF(type)) - eval->subsurface += value; else if (CLOSURE_IS_PHASE(type)) - eval->scatter += value; + eval->volume += value; /* skipping transparent, this function is used by for eval(), will be zero then */ } @@ -98,7 +93,7 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval) #ifdef __PASSES__ if (eval->use_light_pass) { return is_zero(eval->diffuse) && is_zero(eval->glossy) && is_zero(eval->transmission) && - is_zero(eval->transparent) && is_zero(eval->subsurface) && is_zero(eval->scatter); + is_zero(eval->transparent) && is_zero(eval->volume); } else #endif @@ -114,8 +109,7 @@ ccl_device_inline void bsdf_eval_mis(BsdfEval *eval, float value) eval->diffuse *= value; eval->glossy *= value; eval->transmission *= value; - eval->subsurface *= value; - eval->scatter *= value; + eval->volume *= value; /* skipping transparent, this function is used by for eval(), will be zero then */ } @@ -144,8 +138,7 @@ ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value) eval->diffuse *= value; eval->glossy *= value; eval->transmission *= value; - eval->subsurface *= value; - eval->scatter *= value; + eval->volume *= value; /* skipping transparent, this function is used by for eval(), will be zero then */ } @@ -160,7 +153,7 @@ ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval) { #ifdef __PASSES__ if (eval->use_light_pass) { - return eval->diffuse + eval->glossy + eval->transmission + eval->subsurface + eval->scatter; + return eval->diffuse + eval->glossy + eval->transmission + eval->volume; } else #endif @@ -187,19 +180,16 @@ ccl_device_inline void path_radiance_init(KernelGlobals *kg, PathRadiance *L) L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f); L->color_glossy = make_float3(0.0f, 0.0f, 0.0f); L->color_transmission = make_float3(0.0f, 0.0f, 0.0f); - L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f); L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f); L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f); L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f); - L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f); - L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f); + L->direct_volume = make_float3(0.0f, 0.0f, 0.0f); L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f); L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f); L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f); - L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f); - L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f); + L->indirect_volume = make_float3(0.0f, 0.0f, 0.0f); L->transparent = 0.0f; L->emission = make_float3(0.0f, 0.0f, 0.0f); @@ -211,8 +201,7 @@ ccl_device_inline void path_radiance_init(KernelGlobals *kg, PathRadiance *L) L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f); L->state.glossy = make_float3(0.0f, 0.0f, 0.0f); L->state.transmission = make_float3(0.0f, 0.0f, 0.0f); - L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f); - L->state.scatter = make_float3(0.0f, 0.0f, 0.0f); + L->state.volume = make_float3(0.0f, 0.0f, 0.0f); L->state.direct = make_float3(0.0f, 0.0f, 0.0f); } else @@ -264,11 +253,9 @@ ccl_device_inline void path_radiance_bsdf_bounce(KernelGlobals *kg, L_state->diffuse = bsdf_eval->diffuse * value; L_state->glossy = bsdf_eval->glossy * value; L_state->transmission = bsdf_eval->transmission * value; - L_state->subsurface = bsdf_eval->subsurface * value; - L_state->scatter = bsdf_eval->scatter * value; + L_state->volume = bsdf_eval->volume * value; - *throughput = L_state->diffuse + L_state->glossy + L_state->transmission + - L_state->subsurface + L_state->scatter; + *throughput = L_state->diffuse + L_state->glossy + L_state->transmission + L_state->volume; L_state->direct = *throughput; } @@ -449,8 +436,7 @@ ccl_device_inline void path_radiance_accum_light(KernelGlobals *kg, L->direct_diffuse += shaded_throughput * bsdf_eval->diffuse; L->direct_glossy += shaded_throughput * bsdf_eval->glossy; L->direct_transmission += shaded_throughput * bsdf_eval->transmission; - L->direct_subsurface += shaded_throughput * bsdf_eval->subsurface; - L->direct_scatter += shaded_throughput * bsdf_eval->scatter; + L->direct_volume += shaded_throughput * bsdf_eval->volume; if (is_lamp) { L->shadow.x += shadow.x * shadow_fac; @@ -562,15 +548,13 @@ ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L) L->direct_diffuse += L->state.diffuse * L->direct_emission; L->direct_glossy += L->state.glossy * L->direct_emission; L->direct_transmission += L->state.transmission * L->direct_emission; - L->direct_subsurface += L->state.subsurface * L->direct_emission; - L->direct_scatter += L->state.scatter * L->direct_emission; + L->direct_volume += L->state.volume * L->direct_emission; L->indirect = safe_divide_color(L->indirect, L->state.direct); L->indirect_diffuse += L->state.diffuse * L->indirect; L->indirect_glossy += L->state.glossy * L->indirect; L->indirect_transmission += L->state.transmission * L->indirect; - L->indirect_subsurface += L->state.subsurface * L->indirect; - L->indirect_scatter += L->state.scatter * L->indirect; + L->indirect_volume += L->state.volume * L->indirect; } #endif } @@ -582,8 +566,7 @@ ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L) L->state.diffuse = make_float3(0.0f, 0.0f, 0.0f); L->state.glossy = make_float3(0.0f, 0.0f, 0.0f); L->state.transmission = make_float3(0.0f, 0.0f, 0.0f); - L->state.subsurface = make_float3(0.0f, 0.0f, 0.0f); - L->state.scatter = make_float3(0.0f, 0.0f, 0.0f); + L->state.volume = make_float3(0.0f, 0.0f, 0.0f); L->direct_emission = make_float3(0.0f, 0.0f, 0.0f); L->indirect = make_float3(0.0f, 0.0f, 0.0f); @@ -647,10 +630,10 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, if (L->use_light_pass) { path_radiance_sum_indirect(L); - L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + - L->direct_subsurface + L->direct_scatter + L->emission; + L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_volume + + L->emission; L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + - L->indirect_subsurface + L->indirect_scatter; + L->indirect_volume; if (!kernel_data.background.transparent) L_direct += L->background; @@ -666,14 +649,12 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f); L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f); L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f); - L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f); - L->direct_scatter = make_float3(0.0f, 0.0f, 0.0f); + L->direct_volume = make_float3(0.0f, 0.0f, 0.0f); L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f); L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f); L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f); - L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f); - L->indirect_scatter = make_float3(0.0f, 0.0f, 0.0f); + L->indirect_volume = make_float3(0.0f, 0.0f, 0.0f); L->emission = make_float3(0.0f, 0.0f, 0.0f); } @@ -715,7 +696,7 @@ ccl_device_inline void path_radiance_split_denoising(KernelGlobals *kg, kernel_assert(L->use_light_pass); *clean = L->emission + L->background; - *noisy = L->direct_scatter + L->indirect_scatter; + *noisy = L->direct_volume + L->indirect_volume; # define ADD_COMPONENT(flag, component) \ if (kernel_data.film.denoising_flags & flag) \ @@ -729,8 +710,6 @@ ccl_device_inline void path_radiance_split_denoising(KernelGlobals *kg, ADD_COMPONENT(DENOISING_CLEAN_GLOSSY_IND, L->indirect_glossy); ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_DIR, L->direct_transmission); ADD_COMPONENT(DENOISING_CLEAN_TRANSMISSION_IND, L->indirect_transmission); - ADD_COMPONENT(DENOISING_CLEAN_SUBSURFACE_DIR, L->direct_subsurface); - ADD_COMPONENT(DENOISING_CLEAN_SUBSURFACE_IND, L->indirect_subsurface); # undef ADD_COMPONENT #else *noisy = L->emission; @@ -767,14 +746,12 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse); safe_float3_add(L->direct_glossy, L_sample->direct_glossy); safe_float3_add(L->direct_transmission, L_sample->direct_transmission); - safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface); - safe_float3_add(L->direct_scatter, L_sample->direct_scatter); + safe_float3_add(L->direct_volume, L_sample->direct_volume); safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse); safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy); safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission); - safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface); - safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter); + safe_float3_add(L->indirect_volume, L_sample->indirect_volume); safe_float3_add(L->background, L_sample->background); safe_float3_add(L->ao, L_sample->ao); diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index a349b225abb..f1fc697553a 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -71,7 +71,7 @@ ccl_device_inline void compute_light_pass( # ifdef __SUBSURFACE__ /* sample subsurface scattering */ - if ((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) { + if ((pass_filter & BAKE_FILTER_DIFFUSE) && (sd->flag & SD_BSSRDF)) { /* When mixing BSSRDF and BSDF closures we should skip BSDF lighting * if scattering was successful. */ SubsurfaceIndirectRays ss_indirect; @@ -123,7 +123,7 @@ ccl_device_inline void compute_light_pass( # ifdef __SUBSURFACE__ /* sample subsurface scattering */ - if ((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) { + if ((pass_filter & BAKE_FILTER_DIFFUSE) && (sd->flag & SD_BSSRDF)) { /* When mixing BSSRDF and BSDF closures we should skip BSDF lighting * if scattering was successful. */ kernel_branched_path_subsurface_scatter( @@ -178,10 +178,6 @@ ccl_device_inline float3 kernel_bake_shader_bsdf(KernelGlobals *kg, return shader_bsdf_glossy(kg, sd); case SHADER_EVAL_TRANSMISSION: return shader_bsdf_transmission(kg, sd); -# ifdef __SUBSURFACE__ - case SHADER_EVAL_SUBSURFACE: - return shader_bsdf_subsurface(kg, sd); -# endif default: kernel_assert(!"Unknown bake type passed to BSDF evaluate"); return make_float3(0.0f, 0.0f, 0.0f); @@ -385,11 +381,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, if ((pass_filter & BAKE_FILTER_TRANSMISSION_INDIRECT) == BAKE_FILTER_TRANSMISSION_INDIRECT) out += L.indirect_transmission; - if ((pass_filter & BAKE_FILTER_SUBSURFACE_DIRECT) == BAKE_FILTER_SUBSURFACE_DIRECT) - out += L.direct_subsurface; - if ((pass_filter & BAKE_FILTER_SUBSURFACE_INDIRECT) == BAKE_FILTER_SUBSURFACE_INDIRECT) - out += L.indirect_subsurface; - if ((pass_filter & BAKE_FILTER_EMISSION) != 0) out += L.emission; @@ -414,13 +405,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, kg, &sd, &state, L.direct_transmission, L.indirect_transmission, type, pass_filter); break; } - case SHADER_EVAL_SUBSURFACE: { -# ifdef __SUBSURFACE__ - out = kernel_bake_evaluate_direct_indirect( - kg, &sd, &state, L.direct_subsurface, L.indirect_subsurface, type, pass_filter); -# endif - break; - } # endif /* extra */ diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index c63d1149d03..71b176a0a8f 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -145,16 +145,14 @@ ccl_device_noinline_cpu bool direct_emission(KernelGlobals *kg, #ifdef __PASSES__ /* use visibility flag to skip lights */ if (ls->shader & SHADER_EXCLUDE_ANY) { - if (ls->shader & SHADER_EXCLUDE_DIFFUSE) { + if (ls->shader & SHADER_EXCLUDE_DIFFUSE) eval->diffuse = make_float3(0.0f, 0.0f, 0.0f); - eval->subsurface = make_float3(0.0f, 0.0f, 0.0f); - } if (ls->shader & SHADER_EXCLUDE_GLOSSY) eval->glossy = make_float3(0.0f, 0.0f, 0.0f); if (ls->shader & SHADER_EXCLUDE_TRANSMIT) eval->transmission = make_float3(0.0f, 0.0f, 0.0f); if (ls->shader & SHADER_EXCLUDE_SCATTER) - eval->scatter = make_float3(0.0f, 0.0f, 0.0f); + eval->volume = make_float3(0.0f, 0.0f, 0.0f); } #endif diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index e50fa07a885..187e8340c82 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -249,8 +249,6 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, L->color_glossy += shader_bsdf_glossy(kg, sd) * throughput; if (light_flag & PASSMASK_COMPONENT(TRANSMISSION)) L->color_transmission += shader_bsdf_transmission(kg, sd) * throughput; - if (light_flag & PASSMASK_COMPONENT(SUBSURFACE)) - L->color_subsurface += shader_bsdf_subsurface(kg, sd) * throughput; if (light_flag & PASSMASK(MIST)) { /* bring depth into 0..1 range */ @@ -296,11 +294,8 @@ ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, if (light_flag & PASSMASK(TRANSMISSION_INDIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, L->indirect_transmission); - if (light_flag & PASSMASK(SUBSURFACE_INDIRECT)) - kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_indirect, - L->indirect_subsurface); if (light_flag & PASSMASK(VOLUME_INDIRECT)) - kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_indirect, L->indirect_scatter); + kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_indirect, L->indirect_volume); if (light_flag & PASSMASK(DIFFUSE_DIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, L->direct_diffuse); if (light_flag & PASSMASK(GLOSSY_DIRECT)) @@ -308,11 +303,8 @@ ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, if (light_flag & PASSMASK(TRANSMISSION_DIRECT)) kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, L->direct_transmission); - if (light_flag & PASSMASK(SUBSURFACE_DIRECT)) - kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_direct, - L->direct_subsurface); if (light_flag & PASSMASK(VOLUME_DIRECT)) - kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_direct, L->direct_scatter); + kernel_write_pass_float3(buffer + kernel_data.film.pass_volume_direct, L->direct_volume); if (light_flag & PASSMASK(EMISSION)) kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, L->emission); @@ -328,8 +320,6 @@ ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, if (light_flag & PASSMASK(TRANSMISSION_COLOR)) kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, L->color_transmission); - if (light_flag & PASSMASK(SUBSURFACE_COLOR)) - kernel_write_pass_float3(buffer + kernel_data.film.pass_subsurface_color, L->color_subsurface); if (light_flag & PASSMASK(SHADOW)) { float4 shadow = L->shadow; shadow.w = kernel_data.film.pass_shadow_scale; diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index d03faff4242..9120fa7c3f3 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -901,7 +901,8 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd) for (int i = 0; i < sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; - if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) + if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type) || + CLOSURE_IS_BSDF_BSSRDF(sc->type)) eval += sc->weight; } @@ -936,20 +937,6 @@ ccl_device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd) return eval; } -ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd) -{ - float3 eval = make_float3(0.0f, 0.0f, 0.0f); - - for (int i = 0; i < sd->num_closure; i++) { - ShaderClosure *sc = &sd->closure[i]; - - if (CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type)) - eval += sc->weight; - } - - return eval; -} - ccl_device float3 shader_bsdf_average_normal(KernelGlobals *kg, ShaderData *sd) { float3 N = make_float3(0.0f, 0.0f, 0.0f); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 68cb1e974f0..75187ad1bd2 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -220,7 +220,6 @@ typedef enum ShaderEvalType { SHADER_EVAL_DIFFUSE_COLOR, SHADER_EVAL_GLOSSY_COLOR, SHADER_EVAL_TRANSMISSION_COLOR, - SHADER_EVAL_SUBSURFACE_COLOR, SHADER_EVAL_EMISSION, SHADER_EVAL_AOV_COLOR, SHADER_EVAL_AOV_VALUE, @@ -232,7 +231,6 @@ typedef enum ShaderEvalType { SHADER_EVAL_DIFFUSE, SHADER_EVAL_GLOSSY, SHADER_EVAL_TRANSMISSION, - SHADER_EVAL_SUBSURFACE, /* extra */ SHADER_EVAL_ENVIRONMENT, @@ -392,9 +390,6 @@ typedef enum PassType { PASS_TRANSMISSION_DIRECT, PASS_TRANSMISSION_INDIRECT, PASS_TRANSMISSION_COLOR, - PASS_SUBSURFACE_DIRECT, - PASS_SUBSURFACE_INDIRECT, - PASS_SUBSURFACE_COLOR, PASS_VOLUME_DIRECT, PASS_VOLUME_INDIRECT, /* No Scatter color since it's tricky to define what it would even mean. */ @@ -445,23 +440,20 @@ typedef enum eBakePassFilter { BAKE_FILTER_DIFFUSE = (1 << 3), BAKE_FILTER_GLOSSY = (1 << 4), BAKE_FILTER_TRANSMISSION = (1 << 5), - BAKE_FILTER_SUBSURFACE = (1 << 6), - BAKE_FILTER_EMISSION = (1 << 7), - BAKE_FILTER_AO = (1 << 8), + BAKE_FILTER_EMISSION = (1 << 6), + BAKE_FILTER_AO = (1 << 7), } eBakePassFilter; typedef enum BakePassFilterCombos { BAKE_FILTER_COMBINED = (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE | - BAKE_FILTER_GLOSSY | BAKE_FILTER_TRANSMISSION | BAKE_FILTER_SUBSURFACE | - BAKE_FILTER_EMISSION | BAKE_FILTER_AO), + BAKE_FILTER_GLOSSY | BAKE_FILTER_TRANSMISSION | BAKE_FILTER_EMISSION | + BAKE_FILTER_AO), BAKE_FILTER_DIFFUSE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_DIFFUSE), BAKE_FILTER_GLOSSY_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_GLOSSY), BAKE_FILTER_TRANSMISSION_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_TRANSMISSION), - BAKE_FILTER_SUBSURFACE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_SUBSURFACE), BAKE_FILTER_DIFFUSE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE), BAKE_FILTER_GLOSSY_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_GLOSSY), BAKE_FILTER_TRANSMISSION_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_TRANSMISSION), - BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE), } BakePassFilterCombos; typedef enum DenoiseFlag { @@ -471,9 +463,7 @@ typedef enum DenoiseFlag { DENOISING_CLEAN_GLOSSY_IND = (1 << 3), DENOISING_CLEAN_TRANSMISSION_DIR = (1 << 4), DENOISING_CLEAN_TRANSMISSION_IND = (1 << 5), - DENOISING_CLEAN_SUBSURFACE_DIR = (1 << 6), - DENOISING_CLEAN_SUBSURFACE_IND = (1 << 7), - DENOISING_CLEAN_ALL_PASSES = (1 << 8) - 1, + DENOISING_CLEAN_ALL_PASSES = (1 << 6) - 1, } DenoiseFlag; #ifdef __KERNEL_DEBUG__ @@ -493,8 +483,7 @@ typedef ccl_addr_space struct PathRadianceState { float3 diffuse; float3 glossy; float3 transmission; - float3 subsurface; - float3 scatter; + float3 volume; float3 direct; #endif @@ -517,19 +506,16 @@ typedef ccl_addr_space struct PathRadiance { float3 color_diffuse; float3 color_glossy; float3 color_transmission; - float3 color_subsurface; float3 direct_diffuse; float3 direct_glossy; float3 direct_transmission; - float3 direct_subsurface; - float3 direct_scatter; + float3 direct_volume; float3 indirect_diffuse; float3 indirect_glossy; float3 indirect_transmission; - float3 indirect_subsurface; - float3 indirect_scatter; + float3 indirect_volume; float4 shadow; float mist; @@ -583,8 +569,7 @@ typedef struct BsdfEval { float3 glossy; float3 transmission; float3 transparent; - float3 subsurface; - float3 scatter; + float3 volume; #endif #ifdef __SHADOW_TRICKS__ float3 sum_no_mis; @@ -1214,18 +1199,15 @@ typedef struct KernelFilm { int pass_diffuse_color; int pass_glossy_color; int pass_transmission_color; - int pass_subsurface_color; int pass_diffuse_indirect; int pass_glossy_indirect; int pass_transmission_indirect; - int pass_subsurface_indirect; int pass_volume_indirect; int pass_diffuse_direct; int pass_glossy_direct; int pass_transmission_direct; - int pass_subsurface_direct; int pass_volume_direct; int pass_emission; @@ -1252,7 +1234,6 @@ typedef struct KernelFilm { int pass_aov_color; int pass_aov_value; int pad1; - int pad2; /* XYZ to rendering color space transform. float4 instead of float3 to * ensure consistent padding/alignment across devices. */ diff --git a/intern/cycles/kernel/shaders/node_vector_rotate.osl b/intern/cycles/kernel/shaders/node_vector_rotate.osl index a049ee92dbc..533aa7bbe13 100644 --- a/intern/cycles/kernel/shaders/node_vector_rotate.osl +++ b/intern/cycles/kernel/shaders/node_vector_rotate.osl @@ -28,31 +28,6 @@ shader node_vector_rotate(string type = "axis", if (type == "euler_xyz") { VectorOut = transform(euler_to_mat(Rotation), VectorIn - Center) + Center; } - else if (type == "euler_xzy") { - VectorOut = transform(euler_to_mat(point(-Rotation[0], -Rotation[2], -Rotation[1])), - VectorIn - Center) + - Center; - } - else if (type == "euler_yxz") { - VectorOut = transform(euler_to_mat(point(-Rotation[1], -Rotation[0], -Rotation[2])), - VectorIn - Center) + - Center; - } - else if (type == "euler_yzx") { - VectorOut = transform(euler_to_mat(point(Rotation[1], Rotation[2], Rotation[0])), - VectorIn - Center) + - Center; - } - else if (type == "euler_zxy") { - VectorOut = transform(euler_to_mat(point(Rotation[2], Rotation[0], Rotation[1])), - VectorIn - Center) + - Center; - } - else if (type == "euler_zyx") { - VectorOut = transform(euler_to_mat(point(-Rotation[2], -Rotation[1], -Rotation[0])), - VectorIn - Center) + - Center; - } else if (type == "x_axis") { VectorOut = rotate(VectorIn - Center, Angle, point(0.0), vector(1.0, 0.0, 0.0)) + Center; } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index cff2b964c51..38f12ebdf48 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -358,11 +358,6 @@ typedef enum NodeVectorRotateType { NODE_VECTOR_ROTATE_TYPE_AXIS_Y, NODE_VECTOR_ROTATE_TYPE_AXIS_Z, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ, - NODE_VECTOR_ROTATE_TYPE_EULER_XZY, - NODE_VECTOR_ROTATE_TYPE_EULER_YXZ, - NODE_VECTOR_ROTATE_TYPE_EULER_YZX, - NODE_VECTOR_ROTATE_TYPE_EULER_ZXY, - NODE_VECTOR_ROTATE_TYPE_EULER_ZYX, } NodeVectorRotateType; typedef enum NodeVectorTransformType { @@ -532,6 +527,7 @@ typedef enum ClosureType { CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID, CLOSURE_BSDF_PRINCIPLED_SHEEN_ID, CLOSURE_BSDF_DIFFUSE_TOON_ID, + CLOSURE_BSDF_TRANSLUCENT_ID, /* Glossy */ CLOSURE_BSDF_REFLECTION_ID, @@ -554,7 +550,6 @@ typedef enum ClosureType { CLOSURE_BSDF_HAIR_REFLECTION_ID, /* Transmission */ - CLOSURE_BSDF_TRANSLUCENT_ID, CLOSURE_BSDF_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, @@ -595,12 +590,12 @@ typedef enum ClosureType { /* watch this, being lazy with memory usage */ #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_DIFFUSE(type) \ - (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID) + (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_TRANSLUCENT_ID) #define CLOSURE_IS_BSDF_GLOSSY(type) \ ((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID) || \ (type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID)) #define CLOSURE_IS_BSDF_TRANSMISSION(type) \ - (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID) + (type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID) #define CLOSURE_IS_BSDF_BSSRDF(type) \ (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID) #define CLOSURE_IS_BSDF_SINGULAR(type) \ diff --git a/intern/cycles/kernel/svm/svm_vector_rotate.h b/intern/cycles/kernel/svm/svm_vector_rotate.h index c7923e10c53..903a9c1d1db 100644 --- a/intern/cycles/kernel/svm/svm_vector_rotate.h +++ b/intern/cycles/kernel/svm/svm_vector_rotate.h @@ -35,26 +35,8 @@ ccl_device void svm_node_vector_rotate(ShaderData *sd, float3 center = stack_load_float3(stack, center_stack_offset); float3 result = make_float3(0.0f, 0.0f, 0.0f); - if (type != NODE_VECTOR_ROTATE_TYPE_AXIS && type != NODE_VECTOR_ROTATE_TYPE_AXIS_X && - type != NODE_VECTOR_ROTATE_TYPE_AXIS_Y && type != NODE_VECTOR_ROTATE_TYPE_AXIS_Z) { + if (type == NODE_VECTOR_ROTATE_TYPE_EULER_XYZ) { float3 rotation = stack_load_float3(stack, rotation_stack_offset); // Default XYZ. - switch (type) { - case NODE_VECTOR_ROTATE_TYPE_EULER_XZY: - rotation = make_float3(-rotation.x, -rotation.z, -rotation.y); - break; - case NODE_VECTOR_ROTATE_TYPE_EULER_YXZ: - rotation = make_float3(-rotation.y, -rotation.x, -rotation.z); - break; - case NODE_VECTOR_ROTATE_TYPE_EULER_YZX: - rotation = make_float3(rotation.y, rotation.z, rotation.x); - break; - case NODE_VECTOR_ROTATE_TYPE_EULER_ZXY: - rotation = make_float3(rotation.z, rotation.x, rotation.y); - break; - case NODE_VECTOR_ROTATE_TYPE_EULER_ZYX: - rotation = make_float3(-rotation.z, -rotation.y, -rotation.x); - break; - } Transform rotationTransform = euler_to_transform(rotation); result = transform_direction(&rotationTransform, vector - center) + center; } @@ -75,7 +57,7 @@ ccl_device void svm_node_vector_rotate(ShaderData *sd, break; } float angle = stack_load_float(stack, angle_stack_offset); - result = is_zero(axis) ? vector : rotate_around_axis(vector - center, axis, angle) + center; + result = len(axis) ? rotate_around_axis(vector - center, axis, angle) + center : vector; } /* Output */ diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index 9613da7c152..11ccfc95293 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -285,8 +285,6 @@ int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_ return BAKE_FILTER_GLOSSY | component_flags; case SHADER_EVAL_TRANSMISSION: return BAKE_FILTER_TRANSMISSION | component_flags; - case SHADER_EVAL_SUBSURFACE: - return BAKE_FILTER_SUBSURFACE | component_flags; case SHADER_EVAL_COMBINED: return pass_filter; default: diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 00356790261..172ea3dd31b 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -155,7 +155,6 @@ void Pass::add(PassType type, vector<Pass> &passes, const char *name) case PASS_DIFFUSE_COLOR: case PASS_GLOSSY_COLOR: case PASS_TRANSMISSION_COLOR: - case PASS_SUBSURFACE_COLOR: pass.components = 4; break; case PASS_DIFFUSE_DIRECT: @@ -176,12 +175,6 @@ void Pass::add(PassType type, vector<Pass> &passes, const char *name) pass.exposure = true; pass.divide_type = PASS_TRANSMISSION_COLOR; break; - case PASS_SUBSURFACE_DIRECT: - case PASS_SUBSURFACE_INDIRECT: - pass.components = 4; - pass.exposure = true; - pass.divide_type = PASS_SUBSURFACE_COLOR; - break; case PASS_VOLUME_DIRECT: case PASS_VOLUME_INDIRECT: pass.components = 4; @@ -442,9 +435,6 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) case PASS_TRANSMISSION_COLOR: kfilm->pass_transmission_color = kfilm->pass_stride; break; - case PASS_SUBSURFACE_COLOR: - kfilm->pass_subsurface_color = kfilm->pass_stride; - break; case PASS_DIFFUSE_INDIRECT: kfilm->pass_diffuse_indirect = kfilm->pass_stride; break; @@ -454,9 +444,6 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) case PASS_TRANSMISSION_INDIRECT: kfilm->pass_transmission_indirect = kfilm->pass_stride; break; - case PASS_SUBSURFACE_INDIRECT: - kfilm->pass_subsurface_indirect = kfilm->pass_stride; - break; case PASS_VOLUME_INDIRECT: kfilm->pass_volume_indirect = kfilm->pass_stride; break; @@ -469,9 +456,6 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) case PASS_TRANSMISSION_DIRECT: kfilm->pass_transmission_direct = kfilm->pass_stride; break; - case PASS_SUBSURFACE_DIRECT: - kfilm->pass_subsurface_direct = kfilm->pass_stride; - break; case PASS_VOLUME_DIRECT: kfilm->pass_volume_direct = kfilm->pass_stride; break; @@ -521,7 +505,7 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) kfilm->use_display_exposure = pass.exposure && (kfilm->exposure != 1.0f); } else if (pass.type == PASS_DIFFUSE_COLOR || pass.type == PASS_TRANSMISSION_COLOR || - pass.type == PASS_GLOSSY_COLOR || pass.type == PASS_SUBSURFACE_COLOR) { + pass.type == PASS_GLOSSY_COLOR) { kfilm->display_divide_pass_stride = kfilm->pass_stride; } diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 9c909c2131f..f975ef993fc 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -6165,11 +6165,6 @@ NODE_DEFINE(VectorRotateNode) type_enum.insert("y_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Y); type_enum.insert("z_axis", NODE_VECTOR_ROTATE_TYPE_AXIS_Z); type_enum.insert("euler_xyz", NODE_VECTOR_ROTATE_TYPE_EULER_XYZ); - type_enum.insert("euler_xzy", NODE_VECTOR_ROTATE_TYPE_EULER_XZY); - type_enum.insert("euler_yxz", NODE_VECTOR_ROTATE_TYPE_EULER_YXZ); - type_enum.insert("euler_yzx", NODE_VECTOR_ROTATE_TYPE_EULER_YZX); - type_enum.insert("euler_zxy", NODE_VECTOR_ROTATE_TYPE_EULER_ZXY); - type_enum.insert("euler_zyx", NODE_VECTOR_ROTATE_TYPE_EULER_ZYX); SOCKET_ENUM(type, "Type", type_enum, NODE_VECTOR_ROTATE_TYPE_AXIS); SOCKET_IN_VECTOR(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f)); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index acf9ca68889..ae0a2cf863a 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -908,9 +908,6 @@ void Session::set_samples(int samples) params.samples = samples; tile_manager.set_samples(samples); - { - thread_scoped_lock pause_lock(pause_mutex); - } pause_cond.notify_all(); } } @@ -946,6 +943,15 @@ void Session::set_denoising(bool denoising, bool optix_denoising) tile_manager.schedule_denoising = denoising && !buffers; } +void Session::set_denoising_start_sample(int sample) +{ + if (sample != params.denoising_start_sample) { + params.denoising_start_sample = sample; + + pause_cond.notify_all(); + } +} + void Session::wait() { if (session_thread) { @@ -1110,8 +1116,8 @@ void Session::denoise() return; } - /* It can happen that denoising was already enabled, but the scene still needs an update. */ - if (scene->film->need_update || !scene->film->denoising_data_offset) { + /* Do not denoise viewport until the sample at which denoising should start is reached. */ + if (!params.background && tile_manager.state.sample < params.denoising_start_sample) { return; } @@ -1122,6 +1128,11 @@ void Session::denoise() return; } + /* It can happen that denoising was already enabled, but the scene still needs an update. */ + if (scene->film->need_update || !scene->film->denoising_data_offset) { + return; + } + /* Add separate denoising task. */ DeviceTask task(DeviceTask::DENOISE); diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 3ef2b70879a..40ec3979afd 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -53,6 +53,7 @@ class SessionParams { int2 tile_size; TileOrder tile_order; int start_resolution; + int denoising_start_sample; int pixel_size; int threads; @@ -85,6 +86,7 @@ class SessionParams { samples = 1024; tile_size = make_int2(64, 64); start_resolution = INT_MAX; + denoising_start_sample = 0; pixel_size = 1; threads = 0; @@ -109,9 +111,10 @@ class SessionParams { bool modified(const SessionParams ¶ms) { return !(device == params.device && background == params.background && - progressive_refine == params.progressive_refine - /* && samples == params.samples */ - && progressive == params.progressive && experimental == params.experimental && + progressive_refine == params.progressive_refine && + /* samples == params.samples && denoising_start_sample == + params.denoising_start_sample && */ + progressive == params.progressive && experimental == params.experimental && tile_size == params.tile_size && start_resolution == params.start_resolution && pixel_size == params.pixel_size && threads == params.threads && use_profiling == params.use_profiling && @@ -152,9 +155,10 @@ class Session { bool ready_to_reset(); void reset(BufferParams ¶ms, int samples); - void set_samples(int samples); void set_pause(bool pause); + void set_samples(int samples); void set_denoising(bool denoising, bool optix_denoising); + void set_denoising_start_sample(int sample); bool update_scene(); bool load_kernels(bool lock_scene = true); diff --git a/intern/mantaflow/CMakeLists.txt b/intern/mantaflow/CMakeLists.txt index b2a0ab30a0c..d9b64b3a199 100644 --- a/intern/mantaflow/CMakeLists.txt +++ b/intern/mantaflow/CMakeLists.txt @@ -28,6 +28,8 @@ add_definitions(-DWITH_FLUID=1) if(WITH_OPENVDB) add_definitions(-DOPENVDB=1) add_definitions(-DOPENVDB_STATICLIB) +else() + add_definitions(-DOPENVDB=0) endif() if(WIN32) diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl index f7c64244dd6..61da755f02f 100644 --- a/intern/opencolorio/gpu_shader_display_transform.glsl +++ b/intern/opencolorio/gpu_shader_display_transform.glsl @@ -163,6 +163,7 @@ vec4 OCIO_ProcessColor(vec4 col, vec4 col_overlay, vec2 noise_uv) col = OCIO_to_display_linear_with_look(col, lut3d_texture); if (overlay) { + col = clamp(col, 0.0, 1.0); col *= 1.0 - col_overlay.a; col += col_overlay; /* Assumed unassociated alpha. */ } diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c index df8fde40f3c..3ad2da99b9f 100644 --- a/release/datafiles/userdef/userdef_default_theme.c +++ b/release/datafiles/userdef/userdef_default_theme.c @@ -238,9 +238,9 @@ const bTheme U_theme_default = { .menu_shadow_fac = 0.3f, .menu_shadow_width = 4, .editor_outline = RGBA(0x1f1f1fff), - .widget_text_cursor = RGBA(0x3399e6ff), .icon_alpha = 1.0f, .icon_saturation = 0.5f, + .widget_text_cursor = RGBA(0x3399e6ff), .xaxis = RGBA(0xff3352ff), .yaxis = RGBA(0x8bdc00ff), .zaxis = RGBA(0x2890ffff), @@ -324,11 +324,11 @@ const bTheme U_theme_default = { .edge_facesel = RGBA(0x4b4b4bff), .edge_crease = RGBA(0xcc0099ff), .edge_bevel = RGBA(0x00a5ffff), - .face = RGBA(0xffffff12), - .face_select = RGBA(0xffa5526c), - .face_dot = RGBA(0xff8a00ff), + .face = RGBA(0xffffff02), + .face_select = RGBA(0xffa5522e), .face_back = RGBA(0xff0000b3), .face_front = RGBA(0x0000ffb3), + .face_dot = RGBA(0xff8a00ff), .extra_edge_len = RGBA(0x150806ff), .extra_edge_angle = RGBA(0x4d4d00ff), .extra_face_angle = RGBA(0x0000ccff), @@ -363,7 +363,7 @@ const bTheme U_theme_default = { .outline_width = 1, .obcenter_dia = 6, .facedot_size = 3, - .editmesh_active = RGBA(0xffffff80), + .editmesh_active = RGBA(0xffffff33), .clipping_border_3d = RGBA(0x313131ff), .bundle_solid = RGBA(0xc8c8c8ff), .camera_path = RGBA(0x000000ff), @@ -435,6 +435,8 @@ const bTheme U_theme_default = { .vertex_select = RGBA(0xff8500ff), .cframe = RGBA(0x5680c2ff), .time_scrub_background = RGBA(0x292929e6), + .time_marker_line = RGBA(0x00000060), + .time_marker_line_selected = RGBA(0xffffff60), .lastsel_point = RGBA(0xffffffff), .handle_auto = RGBA(0x909000ff), .handle_vect = RGBA(0x409030ff), @@ -490,7 +492,7 @@ const bTheme U_theme_default = { .info_property_text = RGBA(0xffffffff), .info_operator = RGBA(0x3ace87ff), .info_operator_text = RGBA(0xffffffff), - }, + }, .space_action = { .back = RGBA(0x42424200), .title = RGBA(0xeeeeeeff), @@ -526,6 +528,8 @@ const bTheme U_theme_default = { .strip_select = RGBA(0xff8c00cc), .cframe = RGBA(0x5680c2ff), .time_scrub_background = RGBA(0x292929e6), + .time_marker_line = RGBA(0x00000060), + .time_marker_line_selected = RGBA(0xffffff60), .ds_channel = RGBA(0x0f2c4d24), .ds_subchannel = RGBA(0x143e6624), .ds_ipoline = RGBA(0x94e575cc), @@ -580,6 +584,8 @@ const bTheme U_theme_default = { .strip_select = RGBA(0xff8c00ff), .cframe = RGBA(0x5680c2ff), .time_scrub_background = RGBA(0x292929e6), + .time_marker_line = RGBA(0x00000060), + .time_marker_line_selected = RGBA(0xffffff60), .ds_channel = RGBA(0x5a85b2ff), .ds_subchannel = RGBA(0x7d98b3ff), .keyborder = RGBA(0x000000ff), @@ -628,6 +634,8 @@ const bTheme U_theme_default = { .bone_pose = RGBA(0x50c8ff50), .cframe = RGBA(0x5680c2ff), .time_scrub_background = RGBA(0x292929e6), + .time_marker_line = RGBA(0x00000060), + .time_marker_line_selected = RGBA(0xffffff60), .vertex_size = 3, .outline_width = 1, .facedot_size = 4, @@ -909,6 +917,8 @@ const bTheme U_theme_default = { .strip_select = RGBA(0xff8c00ff), .cframe = RGBA(0x5680c2ff), .time_scrub_background = RGBA(0x292929e6), + .time_marker_line = RGBA(0x00000060), + .time_marker_line_selected = RGBA(0xffffff60), .handle_auto = RGBA(0x909000ff), .handle_align = RGBA(0x803060ff), .handle_sel_auto = RGBA(0xf0ff40ff), diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index 20c5c869e83..0195232a59d 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -3404,7 +3404,8 @@ def km_object_non_modal(params): ) items.extend([ - + ("object.mode_set",{"type": 'THREE', "value": 'PRESS'}, + {"properties": [("mode", 'POSE')]}), ("object.mode_set_with_submode",{"type": 'ONE', "value": 'PRESS'}, {"properties": [("mode", 'EDIT'), ("mesh_select_mode", {'VERT'})]}), ("object.mode_set_with_submode",{"type": 'TWO', "value": 'PRESS'}, @@ -3423,7 +3424,6 @@ def km_object_non_modal(params): {"properties": [("mode", 'WEIGHT_PAINT')]}), ("object.mode_set",{"type": 'EIGHT', "value": 'PRESS'}, {"properties": [("mode", 'TEXTURE_PAINT')]}), - ("object.mode_set",{"type": 'TWO', "value": 'PRESS'}, {"properties": [("mode", 'EDIT_GPENCIL')]}), ("object.mode_set",{"type": 'THREE', "value": 'PRESS'}, @@ -3432,9 +3432,7 @@ def km_object_non_modal(params): {"properties": [("mode", 'PAINT_GPENCIL')]}), ("object.mode_set",{"type": 'FIVE', "value": 'PRESS'}, {"properties": [("mode", 'WEIGHT_GPENCIL')]}), - - ("object.mode_set",{"type": 'THREE', "value": 'PRESS'}, - {"properties": [("mode", 'POSE')]}) + ]) return keymap diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py index 121b8f2f401..25244b7f065 100644 --- a/release/scripts/startup/bl_ui/properties_view_layer.py +++ b/release/scripts/startup/bl_ui/properties_view_layer.py @@ -59,14 +59,25 @@ class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel): COMPAT_ENGINES = {'BLENDER_EEVEE'} def draw(self, context): - layout = self.layout + pass - layout.use_property_split = True - flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) +class VIEWLAYER_PT_eevee_layer_passes_data(ViewLayerButtonsPanel, Panel): + bl_label = "Data" + bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes" + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + scene = context.scene + rd = scene.render view_layer = context.view_layer + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) col = flow.column() col.prop(view_layer, "use_pass_combined") col = flow.column() @@ -75,17 +86,83 @@ class VIEWLAYER_PT_eevee_layer_passes(ViewLayerButtonsPanel, Panel): col.prop(view_layer, "use_pass_mist") col = flow.column() col.prop(view_layer, "use_pass_normal") - col = flow.column() - col.prop(view_layer, "use_pass_ambient_occlusion") - col = flow.column() - col.prop(view_layer, "use_pass_subsurface_direct", text="Subsurface Direct") - col = flow.column() - col.prop(view_layer, "use_pass_subsurface_color", text="Subsurface Color") +class VIEWLAYER_PT_eevee_layer_passes_light(ViewLayerButtonsPanel, Panel): + bl_label = "Light" + bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes" + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + layout.use_property_decorate = False + + view_layer = context.view_layer + view_layer_eevee = view_layer.eevee + scene = context.scene + scene_eevee = scene.eevee + + split = layout.split(factor=0.35) + split.use_property_split = False + split.label(text="Diffuse") + row = split.row(align=True) + row.prop(view_layer, "use_pass_diffuse_direct", text="Light", toggle=True) + row.prop(view_layer, "use_pass_diffuse_color", text="Color", toggle=True) + + split = layout.split(factor=0.35) + split.use_property_split = False + split.label(text="Specular") + row = split.row(align=True) + row.prop(view_layer, "use_pass_glossy_direct", text="Light", toggle=True) + row.prop(view_layer, "use_pass_glossy_color", text="Color", toggle=True) + + split = layout.split(factor=0.35) + split.use_property_split = False + split.label(text="Volume") + row = split.row(align=True) + row.prop(view_layer_eevee, "use_pass_volume_transmittance", text="Transmittance", toggle=True) + row.prop(view_layer_eevee, "use_pass_volume_scatter", text="Scatter", toggle=True) + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) + + col = layout.column(align=True) + col.prop(view_layer, "use_pass_emit", text="Emission") + col.prop(view_layer, "use_pass_environment") + col.prop(view_layer, "use_pass_shadow") + row = col.row() + row.prop(view_layer, "use_pass_ambient_occlusion", text="Ambient Occlusion") + row.active = scene_eevee.use_gtao + + +class VIEWLAYER_PT_eevee_layer_passes_effects(ViewLayerButtonsPanel, Panel): + bl_label = "Effects" + bl_parent_id = "VIEWLAYER_PT_eevee_layer_passes" + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + layout.use_property_decorate = False + + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) + + view_layer = context.view_layer + view_layer_eevee = view_layer.eevee + scene = context.scene + scene_eevee = scene.eevee + + col = flow.column() + col.prop(view_layer_eevee, "use_pass_bloom", text="Bloom") + col.active = scene_eevee.use_bloom + classes = ( VIEWLAYER_PT_layer, VIEWLAYER_PT_eevee_layer_passes, + VIEWLAYER_PT_eevee_layer_passes_data, + VIEWLAYER_PT_eevee_layer_passes_light, + VIEWLAYER_PT_eevee_layer_passes_effects, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index 4dc724299f0..d2deb70d4a2 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -216,29 +216,52 @@ class ToolSelectPanelHelper: else: return 0 + # tool flattening + # + # usually 'tools' is already expanded into ToolDef + # but when registering a tool, this can still be a function + # (_tools_flatten is usually called with cls.tools_from_context(context) + # [that already yields from the function]) + # so if item is still a function (e.g._defs_XXX.generate_from_brushes) + # seems like we cannot expand here (have no context yet) + # if we yield None here, this will risk running into duplicate tool bl_idname [in register_tool()] + # but still better than erroring out @staticmethod def _tools_flatten(tools): - for item in tools: - if type(item) is tuple: - yield from item - else: - # May be None. - yield item + for item_parent in tools: + if item_parent is None: + yield None + for item in item_parent if (type(item_parent) is tuple) else (item_parent,): + if item is None or _item_is_fn(item): + yield None + else: + yield item @staticmethod def _tools_flatten_with_tool_index(tools): - for item in tools: - if type(item) is tuple: - i = 0 - for sub_item in item: - if sub_item is None: - yield None, -1 - else: - yield sub_item, i - i += 1 - else: - # May be None. - yield item, -1 + for item_parent in tools: + if item_parent is None: + yield None, -1 + i = 0 + for item in item_parent if (type(item_parent) is tuple) else (item_parent,): + if item is None or _item_is_fn(item): + yield None, -1 + else: + yield item, i + i += 1 + + # Special internal function, gives use items that contain keymaps. + @staticmethod + def _tools_flatten_with_keymap(tools): + for item_parent in tools: + if item_parent is None: + continue + for item in item_parent if (type(item_parent) is tuple) else (item_parent,): + # skip None or generator function + if item is None or _item_is_fn(item): + continue + if item.keymap is not None: + yield item @classmethod def _tool_get_active(cls, context, space_type, mode, with_icon=False): @@ -413,19 +436,6 @@ class ToolSelectPanelHelper: keymap_fn[0](km) keymap_fn[0] = km.name - # Special internal function, gives use items that contain keymaps. - @staticmethod - def _tools_flatten_with_keymap(tools): - for item_parent in tools: - if item_parent is None: - continue - for item in item_parent if (type(item_parent) is tuple) else (item_parent,): - # skip None or generator function - if item is None or _item_is_fn(item): - continue - if item.keymap is not None: - yield item - @classmethod def register(cls): wm = bpy.context.window_manager diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index cd1fc49ac8b..2541613d1e6 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -608,15 +608,6 @@ class _defs_edit_mesh: region_type = context.region.type if not extra: - if props.offset_type == 'PERCENT': - layout.prop(props, "offset_pct") - else: - offset_text = "Width" - if props.offset_type == 'DEPTH': - offset_text = "Depth" - elif props.offset_type == 'OFFSET': - offset_text = "Offset" - layout.prop(props, "offset", text=offset_text) if region_type == 'TOOL_HEADER': layout.prop(props, "offset_type", text="") else: diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 5ca6bbb20b7..e92490bcbdc 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -5415,6 +5415,7 @@ class VIEW3D_PT_shading_lighting(Panel): col.prop(shading, "studiolight_rotate_z", text="Rotation") col.prop(shading, "studiolight_intensity") col.prop(shading, "studiolight_background_alpha") + col.prop(shading, "studiolight_background_blur") col = split.column() # to align properly with above elif shading.type == 'RENDERED': @@ -5438,6 +5439,7 @@ class VIEW3D_PT_shading_lighting(Panel): col.prop(shading, "studiolight_rotate_z", text="Rotation") col.prop(shading, "studiolight_intensity") col.prop(shading, "studiolight_background_alpha") + col.prop(shading, "studiolight_background_blur") col = split.column() # to align properly with above diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 2b592c9e550..725c4c0712d 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -584,9 +584,6 @@ static void blf_draw_gl__start(FontBLF *font) * in BLF_position (old ui_rasterpos_safe). */ - /* always bind the texture for the first glyph */ - font->tex_bind_state = 0; - if ((font->flags & (BLF_ROTATION | BLF_MATRIX | BLF_ASPECT)) == 0) { return; /* glyphs will be translated individually and batched. */ } diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 25ea0770f8b..f0afe184233 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -84,16 +84,19 @@ static void blf_batch_draw_init(void) { GPUVertFormat format = {0}; g_batch.pos_loc = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - g_batch.tex_loc = GPU_vertformat_attr_add(&format, "tex", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); g_batch.col_loc = GPU_vertformat_attr_add( &format, "col", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + g_batch.offset_loc = GPU_vertformat_attr_add(&format, "offset", GPU_COMP_I32, 1, GPU_FETCH_INT); + g_batch.glyph_size_loc = GPU_vertformat_attr_add( + &format, "glyph_size", GPU_COMP_I32, 2, GPU_FETCH_INT); g_batch.verts = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STREAM); GPU_vertbuf_data_alloc(g_batch.verts, BLF_BATCH_DRAW_LEN_MAX); GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step); - GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step); GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step); + GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.offset_loc, &g_batch.offset_step); + GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.glyph_size_loc, &g_batch.glyph_size_step); g_batch.glyph_len = 0; /* A dummy vbo containing 4 points, attribs are not used. */ @@ -177,6 +180,46 @@ void blf_batch_draw_begin(FontBLF *font) } } +static GPUTexture *blf_batch_cache_texture_load(void) +{ + GlyphCacheBLF *gc = g_batch.glyph_cache; + BLI_assert(gc); + BLI_assert(gc->bitmap_len > 0); + + if (gc->bitmap_len > gc->bitmap_len_landed) { + const int tex_width = GPU_texture_width(gc->texture); + + int bitmap_len_landed = gc->bitmap_len_landed; + int remain = gc->bitmap_len - bitmap_len_landed; + int offset_x = bitmap_len_landed % tex_width; + int offset_y = bitmap_len_landed / tex_width; + + /* TODO(germano): Update more than one row in a single call. */ + while (remain) { + int remain_row = tex_width - offset_x; + int width = remain > remain_row ? remain_row : remain; + GPU_texture_update_sub(gc->texture, + GPU_DATA_UNSIGNED_BYTE, + &gc->bitmap_result[bitmap_len_landed], + offset_x, + offset_y, + 0, + width, + 1, + 0); + + bitmap_len_landed += width; + remain -= width; + offset_x = 0; + offset_y += 1; + } + + gc->bitmap_len_landed = bitmap_len_landed; + } + + return gc->texture; +} + void blf_batch_draw(void) { if (g_batch.glyph_len == 0) { @@ -190,7 +233,8 @@ void blf_batch_draw(void) /* We need to flush widget base first to ensure correct ordering. */ UI_widgetbase_draw_cache_flush(); - GPU_texture_bind(g_batch.tex_bind_state, 0); + GPUTexture *texture = blf_batch_cache_texture_load(); + GPU_texture_bind(texture, 0); GPU_vertbuf_data_len_set(g_batch.verts, g_batch.glyph_len); GPU_vertbuf_use(g_batch.verts); /* send data */ @@ -202,8 +246,9 @@ void blf_batch_draw(void) /* restart to 1st vertex data pointers */ GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.pos_loc, &g_batch.pos_step); - GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.tex_loc, &g_batch.tex_step); GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.col_loc, &g_batch.col_step); + GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.offset_loc, &g_batch.offset_step); + GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.glyph_size_loc, &g_batch.glyph_size_step); g_batch.glyph_len = 0; } diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 80d43a49e77..8e88bda37a5 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -143,13 +143,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table)); memset(gc->bucket, 0, sizeof(gc->bucket)); - gc->textures = (GPUTexture **)MEM_callocN(sizeof(GPUTexture *) * 256, __func__); - gc->textures_len = 256; - gc->texture_current = BLF_TEXTURE_UNSET; - gc->offset_x = 3; /* enough padding for blur */ - gc->offset_y = 3; /* enough padding for blur */ - gc->pad = 6; - gc->glyphs_len_max = (int)font->face->num_glyphs; gc->glyphs_len_free = (int)font->face->num_glyphs; gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f; @@ -173,9 +166,6 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) CLAMP_MIN(gc->glyph_width_max, 1); CLAMP_MIN(gc->glyph_height_max, 1); - gc->p2_width = 0; - gc->p2_height = 0; - BLI_addhead(&font->cache, gc); return gc; } @@ -229,52 +219,13 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc) blf_glyph_free(g); } } - for (i = 0; i < gc->textures_len; i++) { - if (gc->textures[i]) { - GPU_texture_free(gc->textures[i]); - } + if (gc->texture) { + GPU_texture_free(gc->texture); } - MEM_freeN(gc->textures); - MEM_freeN(gc); -} - -static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc) -{ - int i; - char error[256]; - - /* move the index. */ - gc->texture_current++; - - if (UNLIKELY(gc->texture_current >= gc->textures_len)) { - gc->textures_len *= 2; - gc->textures = MEM_recallocN((void *)gc->textures, sizeof(GPUTexture *) * gc->textures_len); - } - - gc->p2_width = (int)blf_next_p2( - (unsigned int)((gc->glyphs_len_free * gc->glyph_width_max) + (gc->pad * 2))); - if (gc->p2_width > font->tex_size_max) { - gc->p2_width = font->tex_size_max; + if (gc->bitmap_result) { + MEM_freeN(gc->bitmap_result); } - - i = (int)((gc->p2_width - (gc->pad * 2)) / gc->glyph_width_max); - gc->p2_height = (int)blf_next_p2( - (unsigned int)(((gc->glyphs_len_max / i) + 1) * gc->glyph_height_max + (gc->pad * 2))); - - if (gc->p2_height > font->tex_size_max) { - gc->p2_height = font->tex_size_max; - } - - GPUTexture *tex = GPU_texture_create_nD( - gc->p2_width, gc->p2_height, 0, 2, NULL, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, error); - - GPU_texture_bind(tex, 0); - GPU_texture_wrap_mode(tex, false); - GPU_texture_filters(tex, GPU_NEAREST, GPU_LINEAR); - GPU_texture_clear(tex, GPU_DATA_UNSIGNED_BYTE, NULL); - GPU_texture_unbind(tex); - - gc->textures[gc->texture_current] = tex; + MEM_freeN(gc); } GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c) @@ -377,8 +328,6 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add"); g->c = c; g->idx = (FT_UInt)index; - g->offset_x = -1; - g->offset_y = -1; bitmap = slot->bitmap; g->width = (int)bitmap.width; g->height = (int)bitmap.rows; @@ -418,17 +367,19 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un void blf_glyph_free(GlyphBLF *g) { - /* don't need free the texture, the GlyphCache already - * have a list of all the texture and free it. - */ if (g->bitmap) { MEM_freeN(g->bitmap); } MEM_freeN(g); } -static void blf_texture_draw( - const unsigned char color[4], const float uv[2][2], float x1, float y1, float x2, float y2) +static void blf_texture_draw(const unsigned char color[4], + const int glyph_size[2], + const int offset, + float x1, + float y1, + float x2, + float y2) { /* Only one vertex per glyph, geometry shader expand it into a quad. */ /* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */ @@ -437,8 +388,10 @@ static void blf_texture_draw( y1 + g_batch.ofs[1], x2 + g_batch.ofs[0], y2 + g_batch.ofs[1]); - copy_v4_v4(GPU_vertbuf_raw_step(&g_batch.tex_step), (float *)uv); copy_v4_v4_uchar(GPU_vertbuf_raw_step(&g_batch.col_step), color); + copy_v2_v2_int(GPU_vertbuf_raw_step(&g_batch.glyph_size_step), glyph_size); + *((int *)GPU_vertbuf_raw_step(&g_batch.offset_step)) = offset; + g_batch.glyph_len++; /* Flush cache if it's full. */ if (g_batch.glyph_len == BLF_BATCH_DRAW_LEN_MAX) { @@ -447,45 +400,35 @@ static void blf_texture_draw( } static void blf_texture5_draw(const unsigned char color_in[4], - int tex_w, - int tex_h, - const float uv[2][2], + const int glyph_size[2], + const int offset, float x1, float y1, float x2, float y2) { - float ofs[2] = {2 / (float)tex_w, 2 / (float)tex_h}; - float uv_flag[2][2]; - copy_v4_v4((float *)uv_flag, (float *)uv); + int glyph_size_flag[2]; /* flag the x and y component signs for 5x5 blurring */ - uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]); - uv_flag[0][1] = -(uv_flag[0][1] - ofs[1]); - uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]); - uv_flag[1][1] = -(uv_flag[1][1] + ofs[1]); + glyph_size_flag[0] = -glyph_size[0]; + glyph_size_flag[1] = -glyph_size[1]; - blf_texture_draw(color_in, uv_flag, x1 - 2, y1 + 2, x2 + 2, y2 - 2); + blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2); } static void blf_texture3_draw(const unsigned char color_in[4], - int tex_w, - int tex_h, - const float uv[2][2], + const int glyph_size[2], + const int offset, float x1, float y1, float x2, float y2) { - float ofs[2] = {1 / (float)tex_w, 1 / (float)tex_h}; - float uv_flag[2][2]; - copy_v4_v4((float *)uv_flag, (float *)uv); + int glyph_size_flag[2]; /* flag the x component sign for 3x3 blurring */ - uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]); - uv_flag[0][1] = (uv_flag[0][1] - ofs[1]); - uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]); - uv_flag[1][1] = (uv_flag[1][1] + ofs[1]); + glyph_size_flag[0] = -glyph_size[0]; + glyph_size_flag[1] = glyph_size[1]; - blf_texture_draw(color_in, uv_flag, x1 - 1, y1 + 1, x2 + 1, y2 - 1); + blf_texture_draw(color_in, glyph_size_flag, offset, x1, y1, x2, y2); } static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y) @@ -518,63 +461,38 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl return; } - if (g->build_tex == 0) { + if (!g->cached) { if (font->tex_size_max == -1) { font->tex_size_max = GPU_max_texture_size(); } - if (gc->texture_current == BLF_TEXTURE_UNSET) { - blf_glyph_cache_texture(font, gc); - gc->offset_x = gc->pad; - gc->offset_y = 3; /* enough padding for blur */ - } + g->offset = gc->bitmap_len; - if (gc->offset_x > (gc->p2_width - gc->glyph_width_max)) { - gc->offset_x = gc->pad; - gc->offset_y += gc->glyph_height_max; + int buff_size = g->width * g->height; + int bitmap_len = gc->bitmap_len + buff_size; - if (gc->offset_y > (gc->p2_height - gc->glyph_height_max)) { - gc->offset_y = 3; /* enough padding for blur */ - blf_glyph_cache_texture(font, gc); - } - } + if (bitmap_len > gc->bitmap_len_alloc) { + int w = font->tex_size_max; + int h = bitmap_len / w + 1; - g->tex = gc->textures[gc->texture_current]; - g->offset_x = gc->offset_x; - g->offset_y = gc->offset_y; + gc->bitmap_len_alloc = w * h; + gc->bitmap_result = MEM_reallocN(gc->bitmap_result, (size_t)gc->bitmap_len_alloc); - /* prevent glTexSubImage2D from failing if the character - * asks for pixels out of bounds, this tends only to happen - * with very small sizes (5px high or less) */ - if (UNLIKELY((g->offset_x + g->width) > gc->p2_width)) { - g->width -= (g->offset_x + g->width) - gc->p2_width; - BLI_assert(g->width > 0); - } - if (UNLIKELY((g->offset_y + g->height) > gc->p2_height)) { - g->height -= (g->offset_y + g->height) - gc->p2_height; - BLI_assert(g->height > 0); - } - - GPU_texture_update_sub(g->tex, - GPU_DATA_UNSIGNED_BYTE, - g->bitmap, - g->offset_x, - g->offset_y, - 0, - g->width, - g->height, - 0); + /* Keep in sync with the texture. */ + if (gc->texture) { + GPU_texture_free(gc->texture); + } + gc->texture = GPU_texture_create_nD( + w, h, 0, 1, NULL, GPU_R8, GPU_DATA_UNSIGNED_BYTE, 0, false, NULL); - g->uv[0][0] = ((float)g->offset_x) / ((float)gc->p2_width); - g->uv[0][1] = ((float)g->offset_y) / ((float)gc->p2_height); - g->uv[1][0] = ((float)(g->offset_x + g->width)) / ((float)gc->p2_width); - g->uv[1][1] = ((float)(g->offset_y + g->height)) / ((float)gc->p2_height); + gc->bitmap_len_landed = 0; + } - /* update the x offset for the next glyph. */ - gc->offset_x += (int)BLI_rctf_size_x(&g->box) + gc->pad; + memcpy(&gc->bitmap_result[gc->bitmap_len], g->bitmap, (size_t)buff_size); + gc->bitmap_len = bitmap_len; gc->glyphs_len_free--; - g->build_tex = 1; + g->cached = true; } if (font->flags & BLF_CLIPPING) { @@ -587,27 +505,26 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } } - if (font->tex_bind_state != g->tex) { - blf_batch_draw(); - font->tex_bind_state = g->tex; - GPU_texture_bind(font->tex_bind_state, 0); - } - - g_batch.tex_bind_state = g->tex; + g_batch.glyph_cache = gc; + BLI_assert(g->offset < gc->bitmap_len); if (font->flags & BLF_SHADOW) { rctf rect_ofs; blf_glyph_calc_rect_shadow(&rect_ofs, g, x, y, font); if (font->shadow == 0) { - blf_texture_draw( - font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax); + blf_texture_draw(font->shadow_color, + (int[2]){g->width, g->height}, + g->offset, + rect_ofs.xmin, + rect_ofs.ymin, + rect_ofs.xmax, + rect_ofs.ymax); } else if (font->shadow <= 4) { blf_texture3_draw(font->shadow_color, - gc->p2_width, - gc->p2_height, - g->uv, + (int[2]){g->width, g->height}, + g->offset, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, @@ -615,9 +532,8 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } else { blf_texture5_draw(font->shadow_color, - gc->p2_width, - gc->p2_height, - g->uv, + (int[2]){g->width, g->height}, + g->offset, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, @@ -632,9 +548,8 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl switch (font->blur) { case 3: blf_texture3_draw(font->color, - gc->p2_width, - gc->p2_height, - g->uv, + (int[2]){g->width, g->height}, + g->offset, rect.xmin, rect.ymin, rect.xmax, @@ -642,18 +557,29 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl break; case 5: blf_texture5_draw(font->color, - gc->p2_width, - gc->p2_height, - g->uv, + (int[2]){g->width, g->height}, + g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; default: - blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + blf_texture_draw(font->color, + (int[2]){g->width, g->height}, + g->offset, + rect.xmin, + rect.ymin, + rect.xmax, + rect.ymax); } #else - blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax); + blf_texture_draw(font->color, + (int[2]){g->width, g->height}, + g->offset, + rect.xmin, + rect.ymin, + rect.xmax, + rect.ymax); #endif } diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 45086de0f61..bb1697d7860 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -33,13 +33,13 @@ typedef struct BatchBLF { struct FontBLF *font; /* can only batch glyph from the same font */ struct GPUBatch *batch; struct GPUVertBuf *verts; - struct GPUVertBufRaw pos_step, tex_step, col_step; - unsigned int pos_loc, tex_loc, col_loc; + struct GPUVertBufRaw pos_step, col_step, offset_step, glyph_size_step; + unsigned int pos_loc, col_loc, offset_loc, glyph_size_loc; unsigned int glyph_len; float ofs[2]; /* copy of font->pos */ float mat[4][4]; /* previous call modelmatrix. */ bool enabled, active, simple_shader; - GPUTexture *tex_bind_state; + struct GlyphCacheBLF *glyph_cache; } BatchBLF; extern BatchBLF g_batch; @@ -72,30 +72,16 @@ typedef struct GlyphCacheBLF { struct GlyphBLF *glyph_ascii_table[256]; /* texture array, to draw the glyphs. */ - GPUTexture **textures; - - /* size of the array. */ - unsigned int textures_len; - - /* and the last texture, aka. the current texture. */ - unsigned int texture_current; - - /* We draw every glyph in a big texture, so this is the - * current position inside the texture. */ - int offset_x; - int offset_y; - - /* and the space from one to other. */ - int pad; + GPUTexture *texture; + char *bitmap_result; + int bitmap_len; + int bitmap_len_landed; + int bitmap_len_alloc; /* and the bigger glyph in the font. */ int glyph_width_max; int glyph_height_max; - /* next two integer power of two, to build the texture. */ - int p2_width; - int p2_height; - /* number of glyphs in the font. */ int glyphs_len_max; @@ -125,12 +111,8 @@ typedef struct GlyphBLF { /* avoid conversion to int while drawing */ int advance_i; - /* texture id where this glyph is store. */ - GPUTexture *tex; - /* position inside the texture where this glyph is store. */ - int offset_x; - int offset_y; + int offset; /* Bitmap data, from freetype. Take care that this * can be NULL. @@ -142,9 +124,6 @@ typedef struct GlyphBLF { int height; int pitch; - /* uv coords. */ - float uv[2][2]; - /* X and Y bearing of the glyph. * The X bearing is from the origin to the glyph left bbox edge. * The Y bearing is from the baseline to the top of the glyph edge. @@ -152,8 +131,7 @@ typedef struct GlyphBLF { float pos_x; float pos_y; - /* with value of zero mean that we need build the texture. */ - char build_tex; + bool cached; } GlyphBLF; typedef struct FontBufInfoBLF { @@ -239,9 +217,6 @@ typedef struct FontBLF { /* max texture size. */ int tex_size_max; - /* cache current OpenGL texture to save calls into the API */ - GPUTexture *tex_bind_state; - /* font options. */ int flags; @@ -286,6 +261,4 @@ typedef struct DirBLF { char *path; } DirBLF; -#define BLF_TEXTURE_UNSET ((unsigned int)-1) - #endif /* __BLF_INTERNAL_TYPES_H__ */ diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 09aa4ca7a6b..3e7edb175d9 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 283 -#define BLENDER_SUBVERSION 4 +#define BLENDER_SUBVERSION 5 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 50af6c876b4..d39850a162b 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -49,9 +49,6 @@ struct DerivedMesh *CDDM_from_mesh_ex(struct Mesh *mesh, eCDAllocType alloctype, const struct CustomData_MeshMasks *mask); -/* creates a CDDerivedMesh from the given BMEditMesh */ -DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, const bool use_mdisps); - /* Copies the given DerivedMesh with verts, faces & edges stored as * custom element data. */ diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index a55b5dc7817..5fc4e909fac 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -370,150 +370,6 @@ DerivedMesh *CDDM_from_mesh_ex(Mesh *mesh, return dm; } -/* TODO(campbell): remove, use BKE_mesh_from_bmesh_for_eval_nomain instead. */ - -/* used for both editbmesh and bmesh */ -static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, const bool use_mdisps) -{ - DerivedMesh *dm = CDDM_new(bm->totvert, bm->totedge, 0, bm->totloop, bm->totface); - - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - BMIter iter; - BMVert *eve; - BMEdge *eed; - BMFace *efa; - MVert *mvert = cddm->mvert; - MEdge *medge = cddm->medge; - MLoop *mloop = cddm->mloop; - MPoly *mpoly = cddm->mpoly; - int *index, add_orig; - CustomData_MeshMasks mask = {0}; - unsigned int i, j; - - const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); - const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); - - dm->deformedOnly = 1; - - /* don't add origindex layer if one already exists */ - add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX); - - mask = CD_MASK_DERIVEDMESH; - if (use_mdisps) { - mask.lmask |= CD_MASK_MDISPS; - } - - /* don't process shapekeys, we only feed them through the modifier stack as needed, - * e.g. for applying modifiers or the like*/ - mask.vmask &= ~CD_MASK_SHAPEKEY; - CustomData_merge(&bm->vdata, &dm->vertData, mask.vmask, CD_CALLOC, dm->numVertData); - CustomData_merge(&bm->edata, &dm->edgeData, mask.emask, CD_CALLOC, dm->numEdgeData); - CustomData_merge(&bm->ldata, &dm->loopData, mask.lmask, CD_CALLOC, dm->numLoopData); - CustomData_merge(&bm->pdata, &dm->polyData, mask.pmask, CD_CALLOC, dm->numPolyData); - - index = dm->getVertDataArray(dm, CD_ORIGINDEX); - - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - MVert *mv = &mvert[i]; - - copy_v3_v3(mv->co, eve->co); - - BM_elem_index_set(eve, i); /* set_inline */ - - normal_float_to_short_v3(mv->no, eve->no); - - mv->flag = BM_vert_flag_to_mflag(eve); - - if (cd_vert_bweight_offset != -1) { - mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); - } - - if (add_orig) { - *index++ = i; - } - - CustomData_from_bmesh_block(&bm->vdata, &dm->vertData, eve->head.data, i); - } - bm->elem_index_dirty &= ~BM_VERT; - - index = dm->getEdgeDataArray(dm, CD_ORIGINDEX); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - MEdge *med = &medge[i]; - - BM_elem_index_set(eed, i); /* set_inline */ - - med->v1 = BM_elem_index_get(eed->v1); - med->v2 = BM_elem_index_get(eed->v2); - - med->flag = BM_edge_flag_to_mflag(eed); - - /* handle this differently to editmode switching, - * only enable draw for single user edges rather then calculating angle */ - if ((med->flag & ME_EDGEDRAW) == 0) { - if (eed->l && eed->l == eed->l->radial_next) { - med->flag |= ME_EDGEDRAW; - } - } - - if (cd_edge_crease_offset != -1) { - med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset); - } - if (cd_edge_bweight_offset != -1) { - med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset); - } - - CustomData_from_bmesh_block(&bm->edata, &dm->edgeData, eed->head.data, i); - if (add_orig) { - *index++ = i; - } - } - bm->elem_index_dirty &= ~BM_EDGE; - - index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX); - j = 0; - BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { - BMLoop *l_iter; - BMLoop *l_first; - MPoly *mp = &mpoly[i]; - - BM_elem_index_set(efa, i); /* set_inline */ - - mp->totloop = efa->len; - mp->flag = BM_face_flag_to_mflag(efa); - mp->loopstart = j; - mp->mat_nr = efa->mat_nr; - - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - mloop->v = BM_elem_index_get(l_iter->v); - mloop->e = BM_elem_index_get(l_iter->e); - CustomData_from_bmesh_block(&bm->ldata, &dm->loopData, l_iter->head.data, j); - - BM_elem_index_set(l_iter, j); /* set_inline */ - - j++; - mloop++; - } while ((l_iter = l_iter->next) != l_first); - - CustomData_from_bmesh_block(&bm->pdata, &dm->polyData, efa->head.data, i); - - if (add_orig) { - *index++ = i; - } - } - bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); - - dm->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); - - return dm; -} - -DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps) -{ - return cddm_from_bmesh_ex(em->bm, use_mdisps); -} - DerivedMesh *CDDM_copy(DerivedMesh *source) { CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm"); diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 1d44604384a..7c5e9af728a 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -339,37 +339,32 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map) flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA); BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL); BLI_path_abs(temp_dir, relbase); - if (BLI_exists(temp_dir)) { - BLI_delete(temp_dir, true, true); - } + BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ + BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL); BLI_path_abs(temp_dir, relbase); - if (BLI_exists(temp_dir)) { - BLI_delete(temp_dir, true, true); - } + BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ + BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL); BLI_path_abs(temp_dir, relbase); - if (BLI_exists(temp_dir)) { - BLI_delete(temp_dir, true, true); - } + BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ + mds->cache_frame_pause_data = 0; } if (cache_map & FLUID_DOMAIN_OUTDATED_NOISE) { flags &= ~(FLUID_DOMAIN_BAKING_NOISE | FLUID_DOMAIN_BAKED_NOISE | FLUID_DOMAIN_OUTDATED_NOISE); BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL); BLI_path_abs(temp_dir, relbase); - if (BLI_exists(temp_dir)) { - BLI_delete(temp_dir, true, true); - } + BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ + mds->cache_frame_pause_noise = 0; } if (cache_map & FLUID_DOMAIN_OUTDATED_MESH) { flags &= ~(FLUID_DOMAIN_BAKING_MESH | FLUID_DOMAIN_BAKED_MESH | FLUID_DOMAIN_OUTDATED_MESH); BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL); BLI_path_abs(temp_dir, relbase); - if (BLI_exists(temp_dir)) { - BLI_delete(temp_dir, true, true); - } + BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ + mds->cache_frame_pause_mesh = 0; } if (cache_map & FLUID_DOMAIN_OUTDATED_PARTICLES) { @@ -378,9 +373,8 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map) BLI_path_join( temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL); BLI_path_abs(temp_dir, relbase); - if (BLI_exists(temp_dir)) { - BLI_delete(temp_dir, true, true); - } + BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ + mds->cache_frame_pause_particles = 0; } @@ -388,9 +382,8 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map) flags &= ~(FLUID_DOMAIN_BAKING_GUIDE | FLUID_DOMAIN_BAKED_GUIDE | FLUID_DOMAIN_OUTDATED_GUIDE); BLI_path_join(temp_dir, sizeof(temp_dir), mds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL); BLI_path_abs(temp_dir, relbase); - if (BLI_exists(temp_dir)) { - BLI_delete(temp_dir, true, true); - } + BLI_delete(temp_dir, true, true); /* BLI_exists(filepath) is implicit */ + mds->cache_frame_pause_guide = 0; } mds->cache_flag = flags; diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 9faa61f986d..c27fb59835f 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -49,6 +49,8 @@ #include "RE_render_ext.h" +#include "BLI_hash.h" + #ifdef WITH_OCEANSIM /* Ocean code */ @@ -985,11 +987,15 @@ void BKE_ocean_init(struct Ocean *o, } } - /*srand(seed);*/ rng = BLI_rng_new(seed); for (i = 0; i < o->_M; i++) { for (j = 0; j < o->_N; j++) { + /* This ensures we get a value tied to the surface location, avoiding dramatic surface + * change with changing resolution. */ + int new_seed = seed + BLI_hash_int_2d(o->_kx[i] * 360.0f, o->_kz[j] * 360.0f); + + BLI_rng_seed(rng, new_seed); float r1 = gaussRand(rng); float r2 = gaussRand(rng); diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 500c58095e6..483838ed741 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -140,7 +140,7 @@ static void tracking_dopesheet_free(MovieTrackingDopesheet *dopesheet) { MovieTrackingDopesheetChannel *channel; - /* Free channel's sergments. */ + /* Free channel's segments. */ channel = dopesheet->channels.first; while (channel) { if (channel->segments) { diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 5c20e57181e..3ee22e4ad0a 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -73,6 +73,29 @@ int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_ int BLI_wstat(const wchar_t *path, BLI_stat_t *buffer); #endif +typedef enum eFileAttributes { + FILE_ATTR_READONLY = 1 << 0, /* Read-only or Immutable. */ + FILE_ATTR_HIDDEN = 1 << 1, /* Hidden or invisible. */ + FILE_ATTR_SYSTEM = 1 << 2, /* Used by the Operating System. */ + FILE_ATTR_ARCHIVE = 1 << 3, /* Marked as archived. */ + FILE_ATTR_COMPRESSED = 1 << 4, /* Compressed. */ + FILE_ATTR_ENCRYPTED = 1 << 5, /* Encrypted. */ + FILE_ATTR_RESTRICTED = 1 << 6, /* Protected by OS. */ + FILE_ATTR_TEMPORARY = 1 << 7, /* Used for temporary storage. */ + FILE_ATTR_SPARSE_FILE = 1 << 8, /* Sparse File. */ + FILE_ATTR_OFFLINE = 1 << 9, /* Data is not immediately available. */ + FILE_ATTR_ALIAS = 1 << 10, /* Mac Alias or Windows Lnk. File-based redirection. */ + FILE_ATTR_REPARSE_POINT = 1 << 11, /* File has associated reparse point. */ + FILE_ATTR_SYMLINK = 1 << 12, /* Reference to another file. */ + FILE_ATTR_JUNCTION_POINT = 1 << 13, /* Folder Symlink. */ + FILE_ATTR_MOUNT_POINT = 1 << 14, /* Volume mounted as a folder. */ + FILE_ATTR_HARDLINK = 1 << 15, /* Duplicated directory entry. */ +} eFileAttributes; + +#define FILE_ATTR_ANY_LINK \ + (FILE_ATTR_ALIAS | FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYMLINK | FILE_ATTR_JUNCTION_POINT | \ + FILE_ATTR_MOUNT_POINT | FILE_ATTR_HARDLINK) + /* Directories */ struct direntry; @@ -83,6 +106,7 @@ bool BLI_dir_create_recursive(const char *dir) ATTR_NONNULL(); double BLI_dir_free_space(const char *dir) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); char *BLI_current_working_dir(char *dir, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +eFileAttributes BLI_file_attributes(const char *path); /* Filelist */ diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 7c481868d64..d1d8c4fa2e0 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -199,6 +199,70 @@ size_t BLI_file_size(const char *path) return stats.st_size; } +eFileAttributes BLI_file_attributes(const char *path) +{ + int ret = 0; + +#ifdef WIN32 + wchar_t wline[FILE_MAXDIR]; + BLI_strncpy_wchar_from_utf8(wline, path, ARRAY_SIZE(wline)); + DWORD attr = GetFileAttributesW(wline); + if (attr & FILE_ATTRIBUTE_READONLY) { + ret |= FILE_ATTR_READONLY; + } + if (attr & FILE_ATTRIBUTE_HIDDEN) { + ret |= FILE_ATTR_HIDDEN; + } + if (attr & FILE_ATTRIBUTE_SYSTEM) { + ret |= FILE_ATTR_SYSTEM; + } + if (attr & FILE_ATTRIBUTE_ARCHIVE) { + ret |= FILE_ATTR_ARCHIVE; + } + if (attr & FILE_ATTRIBUTE_COMPRESSED) { + ret |= FILE_ATTR_COMPRESSED; + } + if (attr & FILE_ATTRIBUTE_ENCRYPTED) { + ret |= FILE_ATTR_ENCRYPTED; + } + if (attr & FILE_ATTRIBUTE_TEMPORARY) { + ret |= FILE_ATTR_TEMPORARY; + } + if (attr & FILE_ATTRIBUTE_SPARSE_FILE) { + ret |= FILE_ATTR_SPARSE_FILE; + } + if (attr & FILE_ATTRIBUTE_OFFLINE) { + ret |= FILE_ATTR_OFFLINE; + } + if (attr & FILE_ATTRIBUTE_REPARSE_POINT) { + ret |= FILE_ATTR_REPARSE_POINT; + } + +#endif + +#ifdef __APPLE__ + + /* TODO: + * If Hidden (Invisible) set FILE_ATTR_HIDDEN + * If Locked set FILE_ATTR_READONLY + * If Restricted set FILE_ATTR_RESTRICTED + */ + +#endif + +#ifdef __linux__ + UNUSED_VARS(path); + + /* TODO: + * If Immutable set FILE_ATTR_READONLY + * If Archived set FILE_ATTR_ARCHIVE + */ + +#endif + + return ret; +} + /** * Returns the st_mode from stat-ing the specified path name, or 0 if stat fails * (most likely doesn't exist or no access). diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index f23e4b5e2a4..7c70728e50c 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -147,6 +147,23 @@ static void do_versions_nodetree_convert_angle(bNodeTree *ntree) static void do_versions_image_settings_2_60(Scene *sce) { + /* RenderData.subimtype flag options for imtype */ + enum { + R_OPENEXR_HALF = (1 << 0), + R_OPENEXR_ZBUF = (1 << 1), + R_PREVIEW_JPG = (1 << 2), + R_CINEON_LOG = (1 << 3), + R_TIFF_16BIT = (1 << 4), + + R_JPEG2K_12BIT = (1 << 5), + /* Jpeg2000 */ + R_JPEG2K_16BIT = (1 << 6), + R_JPEG2K_YCC = (1 << 7), + /* when disabled use RGB */ + R_JPEG2K_CINE_PRESET = (1 << 8), + R_JPEG2K_CINE_48FPS = (1 << 9), + }; + /* note: rd->subimtype is moved into individual settings now and no longer * exists */ RenderData *rd = &sce->r; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index a24165713aa..627b38a58e8 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -3364,7 +3364,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } for (Image *image = bmain->images.first; image; image = image->id.next) { - image->flag &= ~(IMA_FLAG_UNUSED_0 | IMA_FLAG_UNUSED_1 | IMA_FLAG_UNUSED_4 | + image->flag &= ~(IMA_HIGH_BITDEPTH | IMA_FLAG_UNUSED_1 | IMA_FLAG_UNUSED_4 | IMA_FLAG_UNUSED_6 | IMA_FLAG_UNUSED_8 | IMA_FLAG_UNUSED_15 | IMA_FLAG_UNUSED_16); } @@ -4466,18 +4466,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend - * - "versioning_userdef.c", #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ - + if (!MAIN_VERSION_ATLEAST(bmain, 283, 5)) { /* Alembic Transform Cache changed from world to local space. */ LISTBASE_FOREACH (Object *, ob, &bmain->objects) { LISTBASE_FOREACH (bConstraint *, con, &ob->constraints) { @@ -4498,5 +4487,32 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Add Lookdev blur property. */ + if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "float", "studiolight_blur")) { + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + v3d->shading.studiolight_blur = 0.5f; + } + } + } + } + } + } + + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ } } diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 94ee8d46675..f70988c9277 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -175,6 +175,19 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) FROM_DEFAULT_V4_UCHAR(space_info.info_operator_text); } + if (!USER_VERSION_ATLEAST(283, 5)) { + FROM_DEFAULT_V4_UCHAR(space_graph.time_marker_line); + FROM_DEFAULT_V4_UCHAR(space_action.time_marker_line); + FROM_DEFAULT_V4_UCHAR(space_nla.time_marker_line); + FROM_DEFAULT_V4_UCHAR(space_sequencer.time_marker_line); + FROM_DEFAULT_V4_UCHAR(space_clip.time_marker_line); + FROM_DEFAULT_V4_UCHAR(space_graph.time_marker_line_selected); + FROM_DEFAULT_V4_UCHAR(space_action.time_marker_line_selected); + FROM_DEFAULT_V4_UCHAR(space_nla.time_marker_line_selected); + FROM_DEFAULT_V4_UCHAR(space_sequencer.time_marker_line_selected); + FROM_DEFAULT_V4_UCHAR(space_clip.time_marker_line_selected); + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index e45644f001f..3e7fb702d6a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -28,6 +28,8 @@ #include <stdio.h> #include <stdlib.h> #include <cstring> /* required for STREQ later on. */ +#include <deque> +#include <unordered_set> #include "MEM_guardedalloc.h" @@ -119,6 +121,9 @@ extern "C" { namespace DEG { +using std::deque; +using std::unordered_set; + /* ***************** */ /* Relations Builder */ @@ -1330,48 +1335,6 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id) /* create the driver's relations to targets */ build_driver(id, fcu); - /* Special case for array drivers: we can not multithread them because - * of the way how they work internally: animation system will write the - * whole array back to RNA even when changing individual array value. - * - * Some tricky things here: - * - array_index is -1 for single channel drivers, meaning we only have - * to do some magic when array_index is not -1. - * - We do relation from next array index to a previous one, so we don't - * have to deal with array index 0. - * - * TODO(sergey): Avoid liner lookup somehow. */ - if (fcu->array_index > 0) { - FCurve *fcu_prev = nullptr; - LISTBASE_FOREACH (FCurve *, fcu_candidate, &adt->drivers) { - /* Writing to different RNA paths is */ - const char *rna_path = fcu->rna_path ? fcu->rna_path : ""; - if (!STREQ(fcu_candidate->rna_path, rna_path)) { - continue; - } - /* We only do relation from previous fcurve to previous one. */ - if (fcu_candidate->array_index >= fcu->array_index) { - continue; - } - /* Choose fcurve with highest possible array index. */ - if (fcu_prev == nullptr || fcu_candidate->array_index > fcu_prev->array_index) { - fcu_prev = fcu_candidate; - } - } - if (fcu_prev != nullptr) { - OperationKey prev_driver_key(id, - NodeType::PARAMETERS, - OperationCode::DRIVER, - fcu_prev->rna_path ? fcu_prev->rna_path : "", - fcu_prev->array_index); - OperationKey driver_key(id, - NodeType::PARAMETERS, - OperationCode::DRIVER, - fcu->rna_path ? fcu->rna_path : "", - fcu->array_index); - add_relation(prev_driver_key, driver_key, "Driver Order"); - } - } /* prevent driver from occurring before own animation... */ if (adt->action || adt->nla_tracks.first) { @@ -1488,7 +1451,11 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) } else { /* If it's not a Bone, handle the generic single dependency case. */ - add_relation(driver_key, property_entry_key, "Driver -> Driven Property"); + Node *node_to = get_node(property_entry_key); + if (node_to != nullptr) { + add_relation(driver_key, property_entry_key, "Driver -> Driven Property"); + } + /* Similar to the case with f-curves, driver might drive a nested * data-block, which means driver execution should wait for that * data-block to be copied. */ @@ -2706,6 +2673,116 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) #endif } +static bool is_reachable(const Node *const from, const Node *const to) +{ + if (from == to) { + return true; + } + + // Perform a graph walk from 'to' towards its incoming connections. + // Walking from 'from' towards its outgoing connections is 10x slower on the Spring rig. + deque<const Node *> queue; + unordered_set<const Node *> seen; + queue.push_back(to); + while (!queue.empty()) { + // Visit the next node to inspect. + const Node *visit = queue.back(); + queue.pop_back(); + + if (visit == from) { + return true; + } + + // Queue all incoming relations that we haven't seen before. + for (Relation *relation : visit->inlinks) { + const Node *prev_node = relation->from; + if (seen.insert(prev_node).second) { + queue.push_back(prev_node); + } + } + } + return false; +} + +void DepsgraphRelationBuilder::build_driver_relations() +{ + for (IDNode *id_node : graph_->id_nodes) { + build_driver_relations(id_node); + } +} + +void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node) +{ + /* Add relations between drivers that write to the same datablock. + * + * This prevents threading issues when two separate RNA properties write to + * the same memory address. For example: + * - Drivers on individual array elements, as the animation system will write + * the whole array back to RNA even when changing individual array value. + * - Drivers on RNA properties that map to a single bit flag. Changing the RNA + * value will write the entire int containing the bit, in a non-thread-safe + * way. + */ + ID *id_orig = id_node->id_orig; + AnimData *adt = BKE_animdata_from_id(id_orig); + if (adt == nullptr) { + return; + } + + // Mapping from RNA prefix -> set of driver evaluation nodes: + typedef vector<Node *> DriverGroup; + typedef map<string, DriverGroup> DriverGroupMap; + DriverGroupMap driver_groups; + + LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { + // Get the RNA path except the part after the last dot. + char *last_dot = strrchr(fcu->rna_path, '.'); + string rna_prefix; + if (last_dot != nullptr) { + rna_prefix = string(fcu->rna_path, last_dot); + } + + // Insert this driver node into the group belonging to the RNA prefix. + OperationKey driver_key( + id_orig, NodeType::PARAMETERS, OperationCode::DRIVER, fcu->rna_path, fcu->array_index); + Node *node_driver = get_node(driver_key); + driver_groups[rna_prefix].push_back(node_driver); + } + + for (pair<string, DriverGroup> prefix_group : driver_groups) { + // For each node in the driver group, try to connect it to another node + // in the same group without creating any cycles. + int num_drivers = prefix_group.second.size(); + for (int from_index = 0; from_index < num_drivers; ++from_index) { + Node *op_from = prefix_group.second[from_index]; + + // Start by trying the next node in the group. + for (int to_offset = 1; to_offset < num_drivers - 1; ++to_offset) { + int to_index = (from_index + to_offset) % num_drivers; + Node *op_to = prefix_group.second[to_index]; + + // Investigate whether this relation would create a dependency cycle. + // Example graph: + // A -> B -> C + // and investigating a potential connection C->A. Because A->C is an + // existing transitive connection, adding C->A would create a cycle. + if (is_reachable(op_to, op_from)) { + continue; + } + + // No need to directly connect this node if there is already a transitive connection. + if (is_reachable(op_from, op_to)) { + break; + } + + add_operation_relation( + op_from->get_exit_operation(), op_to->get_entry_operation(), "Driver Serialisation"); + break; + } + } + } +} + /* **** ID traversal callbacks functions **** */ void DepsgraphRelationBuilder::modifier_walk(void *user_data, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 11eb31c68f6..7da3577a7b5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -302,6 +302,8 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { virtual void build_copy_on_write_relations(); virtual void build_copy_on_write_relations(IDNode *id_node); + virtual void build_driver_relations(); + virtual void build_driver_relations(IDNode *id_node); template<typename KeyType> OperationNode *find_operation_node(const KeyType &key); diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index a570e042c26..3fe585ff73c 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -251,6 +251,7 @@ void DEG_graph_build_from_view_layer(Depsgraph *graph, relation_builder.begin_build(); relation_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY); relation_builder.build_copy_on_write_relations(); + relation_builder.build_driver_relations(); /* Finalize building. */ graph_build_finalize_common(deg_graph, bmain); /* Finish statistics. */ @@ -284,6 +285,7 @@ void DEG_graph_build_for_render_pipeline(Depsgraph *graph, relation_builder.begin_build(); relation_builder.build_scene_render(scene, view_layer); relation_builder.build_copy_on_write_relations(); + relation_builder.build_driver_relations(); /* Finalize building. */ graph_build_finalize_common(deg_graph, bmain); /* Finish statistics. */ @@ -317,6 +319,7 @@ void DEG_graph_build_for_compositor_preview( relation_builder.build_scene_render(scene, view_layer); relation_builder.build_nodetree(nodetree); relation_builder.build_copy_on_write_relations(); + relation_builder.build_driver_relations(); /* Finalize building. */ graph_build_finalize_common(deg_graph, bmain); /* Finish statistics. */ @@ -458,6 +461,7 @@ void DEG_graph_build_from_ids(Depsgraph *graph, relation_builder.build_id(ids[i]); } relation_builder.build_copy_on_write_relations(); + relation_builder.build_driver_relations(); /* Finalize building. */ graph_build_finalize_common(deg_graph, bmain); /* Finish statistics. */ diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 37fe04e9d8a..6d7b422c4fb 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -219,6 +219,8 @@ data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_geom.glsl SR data_to_c_simple(engines/eevee/shaders/lightprobe_planar_downsample_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/prepass_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/prepass_vert.glsl SRC) +data_to_c_simple(engines/eevee/shaders/shadow_accum_frag.glsl SRC) + data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC) @@ -232,6 +234,7 @@ data_to_c_simple(engines/eevee/shaders/renderpass_postprocess_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC) +data_to_c_simple(engines/eevee/shaders/volumetric_accum_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/volumetric_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/volumetric_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/volumetric_geom.glsl SRC) @@ -242,7 +245,6 @@ data_to_c_simple(engines/eevee/shaders/volumetric_integration_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_cavity_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_cavity_frag.glsl SRC) -data_to_c_simple(engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_common_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_data_lib.glsl SRC) data_to_c_simple(engines/workbench/shaders/workbench_deferred_composite_frag.glsl SRC) @@ -389,6 +391,7 @@ data_to_c_simple(engines/overlay/shaders/sculpt_mask_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/volume_velocity_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/wireframe_vert.glsl SRC) data_to_c_simple(engines/overlay/shaders/wireframe_frag.glsl SRC) +data_to_c_simple(engines/overlay/shaders/xray_fade_frag.glsl SRC) list(APPEND INC ) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 647d8a0841f..2462603632f 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -48,23 +48,7 @@ struct bContext; struct rcti; #include "DNA_object_enums.h" - -/* Buffer and textures used by the viewport by default */ -typedef struct DefaultFramebufferList { - struct GPUFrameBuffer *default_fb; - struct GPUFrameBuffer *overlay_fb; - struct GPUFrameBuffer *in_front_fb; - struct GPUFrameBuffer *color_only_fb; - struct GPUFrameBuffer *depth_only_fb; - struct GPUFrameBuffer *overlay_only_fb; -} DefaultFramebufferList; - -typedef struct DefaultTextureList { - struct GPUTexture *color; - struct GPUTexture *color_overlay; - struct GPUTexture *depth; - struct GPUTexture *depth_in_front; -} DefaultTextureList; +#include "DRW_engine_types.h" void DRW_engines_register(void); void DRW_engines_free(void); diff --git a/source/blender/draw/DRW_engine_types.h b/source/blender/draw/DRW_engine_types.h new file mode 100644 index 00000000000..dd56f87182c --- /dev/null +++ b/source/blender/draw/DRW_engine_types.h @@ -0,0 +1,51 @@ +/* + * 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 2016, Blender Foundation. + */ + +/** \file + * \ingroup draw + */ + +#ifndef __DRW_ENGINE_TYPES_H__ +#define __DRW_ENGINE_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Buffer and textures used by the viewport by default */ +typedef struct DefaultFramebufferList { + struct GPUFrameBuffer *default_fb; + struct GPUFrameBuffer *overlay_fb; + struct GPUFrameBuffer *in_front_fb; + struct GPUFrameBuffer *color_only_fb; + struct GPUFrameBuffer *depth_only_fb; + struct GPUFrameBuffer *overlay_only_fb; +} DefaultFramebufferList; + +typedef struct DefaultTextureList { + struct GPUTexture *color; + struct GPUTexture *color_overlay; + struct GPUTexture *depth; + struct GPUTexture *depth_in_front; +} DefaultTextureList; + +#ifdef __cplusplus +} +#endif + +#endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_bloom.c b/source/blender/draw/engines/eevee/eevee_bloom.c index c6cc336db56..53465455d57 100644 --- a/source/blender/draw/engines/eevee/eevee_bloom.c +++ b/source/blender/draw/engines/eevee/eevee_bloom.c @@ -40,6 +40,8 @@ static struct { extern char datatoc_effect_bloom_frag_glsl[]; +const bool use_highres = true; + static void eevee_create_shader_bloom(void) { e_data.bloom_blit_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, @@ -179,7 +181,8 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, - bool upsample) + bool upsample, + bool resolve) { struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); @@ -193,6 +196,10 @@ static DRWShadingGroup *eevee_create_bloom_pass(const char *name, DRW_shgroup_uniform_texture_ref(grp, "baseBuffer", &effects->unf_base_buffer); DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1); } + if (resolve) { + DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1); + DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", true); + } return grp; } @@ -203,6 +210,8 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; + psl->bloom_accum_ps = NULL; + if ((effects->enabled_effects & EFFECT_BLOOM) != 0) { /** Bloom algorithm * @@ -234,29 +243,41 @@ void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *ved * </pre> */ DRWShadingGroup *grp; - const bool use_highres = true; const bool use_antiflicker = true; eevee_create_bloom_pass("Bloom Downsample First", effects, e_data.bloom_downsample_sh[use_antiflicker], &psl->bloom_downsample_first, + false, + false); + eevee_create_bloom_pass("Bloom Downsample", + effects, + e_data.bloom_downsample_sh[0], + &psl->bloom_downsample, + false, false); - eevee_create_bloom_pass( - "Bloom Downsample", effects, e_data.bloom_downsample_sh[0], &psl->bloom_downsample, false); eevee_create_bloom_pass("Bloom Upsample", effects, e_data.bloom_upsample_sh[use_highres], &psl->bloom_upsample, - true); + true, + false); - grp = eevee_create_bloom_pass( - "Bloom Blit", effects, e_data.bloom_blit_sh[use_antiflicker], &psl->bloom_blit, false); + grp = eevee_create_bloom_pass("Bloom Blit", + effects, + e_data.bloom_blit_sh[use_antiflicker], + &psl->bloom_blit, + false, + false); DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1); DRW_shgroup_uniform_float(grp, "clampIntensity", &effects->bloom_clamp, 1); - grp = eevee_create_bloom_pass( - "Bloom Resolve", effects, e_data.bloom_resolve_sh[use_highres], &psl->bloom_resolve, true); - DRW_shgroup_uniform_vec3(grp, "bloomColor", effects->bloom_color, 1); + grp = eevee_create_bloom_pass("Bloom Resolve", + effects, + e_data.bloom_resolve_sh[use_highres], + &psl->bloom_resolve, + true, + true); } } @@ -322,6 +343,47 @@ void EEVEE_bloom_draw(EEVEE_Data *vedata) } } +void EEVEE_bloom_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + uint UNUSED(tot_samples)) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + /* Create FrameBuffer. */ + DRW_texture_ensure_fullscreen_2d(&txl->bloom_accum, GPU_R11F_G11F_B10F, 0); + + GPU_framebuffer_ensure_config(&fbl->bloom_pass_accum_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->bloom_accum)}); + + /* Create Pass and shgroup. */ + DRWShadingGroup *grp = eevee_create_bloom_pass("Bloom Accumulate", + effects, + e_data.bloom_resolve_sh[use_highres], + &psl->bloom_accum_ps, + true, + true); + DRW_shgroup_uniform_bool_copy(grp, "bloomAddBase", false); +} + +void EEVEE_bloom_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + + if (stl->g_data->render_passes & EEVEE_RENDER_PASS_BLOOM) { + GPU_framebuffer_bind(fbl->bloom_pass_accum_fb); + DRW_draw_pass(psl->bloom_accum_ps); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + void EEVEE_bloom_free(void) { for (int i = 0; i < 2; i++) { diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index dd70ee1bd4b..e586fc7b1db 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -54,6 +54,9 @@ 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]); + } } EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void) diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index a20921b639f..90bfad45f60 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -170,7 +170,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_subsurface_init(sldata, vedata); /* Force normal buffer creation. */ - if (!minimal && (stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { + if (!minimal && (stl->g_data->render_passes & EEVEE_RENDER_PASS_NORMAL) != 0) { effects->enabled_effects |= EFFECT_NORMAL_BUFFER; } @@ -333,6 +333,8 @@ 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_mat4(grp, "currPersinv", effects->velocity_curr_persinv); DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat); DRW_shgroup_call(grp, quad, NULL); @@ -513,7 +515,7 @@ static void EEVEE_velocity_resolve(EEVEE_Data *vedata) DRW_view_persmat_get(view, effects->velocity_past_persmat, false); } -void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_TextureList *txl = vedata->txl; EEVEE_FramebufferList *fbl = vedata->fbl; @@ -541,6 +543,10 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) EEVEE_temporal_sampling_draw(vedata); EEVEE_bloom_draw(vedata); + /* Post effect render passes are done here just after the drawing of the effects and just before + * the swapping of the buffers. */ + EEVEE_renderpasses_output_accumulate(sldata, vedata, true); + /* Save the final texture and framebuffer for final transformation or read. */ effects->final_tx = effects->source_buffer; effects->final_fb = (effects->target_buffer != fbl->main_color_fb) ? fbl->main_fb : diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index e3b50bb2142..6480847092b 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -151,7 +151,8 @@ void EEVEE_cache_populate(void *vedata, Object *ob) static void eevee_cache_finish(void *vedata) { EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); - EEVEE_PrivateData *g_data = ((EEVEE_Data *)vedata)->stl->g_data; + EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; + EEVEE_PrivateData *g_data = stl->g_data; const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); @@ -307,6 +308,9 @@ static void eevee_draw_scene(void *vedata) /* Volumetrics Resolve Opaque */ EEVEE_volumes_resolve(sldata, vedata); + /* Renderpasses */ + EEVEE_renderpasses_output_accumulate(sldata, vedata, false); + /* Transparent */ /* TODO(fclem): should be its own Framebuffer. * This is needed because dualsource blending only works with 1 color buffer. */ @@ -321,8 +325,6 @@ static void eevee_draw_scene(void *vedata) EEVEE_draw_effects(sldata, vedata); DRW_stats_group_end(); - EEVEE_renderpasses_output_accumulate(sldata, vedata); - DRW_view_set_active(NULL); if (DRW_state_is_image_render() && (stl->effects->enabled_effects & EFFECT_SSR) && @@ -336,7 +338,7 @@ static void eevee_draw_scene(void *vedata) } } - if ((stl->g_data->render_passes & SCE_PASS_COMBINED) > 0) { + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_COMBINED) != 0) { /* Transfer result to default framebuffer. */ GPU_framebuffer_bind(dfbl->default_fb); DRW_transform_none(stl->effects->final_tx); @@ -416,9 +418,8 @@ static void eevee_render_to_image(void *vedata, const rcti *rect) { const DRWContextState *draw_ctx = DRW_context_state_get(); - EEVEE_render_init(vedata, engine, draw_ctx->depsgraph); - if (RE_engine_test_break(engine)) { + if (!EEVEE_render_init(vedata, engine, draw_ctx->depsgraph)) { return; } diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index e8e5614e4d4..2b11a608bd0 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -264,7 +264,7 @@ static bool EEVEE_lightcache_validate(const LightCache *light_cache, if ((irr_size[0] == light_cache->grid_tx.tex_size[0]) && (irr_size[1] == light_cache->grid_tx.tex_size[1]) && (irr_size[2] == light_cache->grid_tx.tex_size[2]) && (grid_len == light_cache->grid_len)) { - int mip_len = (int)(floorf(log2f(cube_res)) - MIN_CUBE_LOD_LEVEL); + int mip_len = log2_floor_u(cube_res) - MIN_CUBE_LOD_LEVEL; if ((cube_res == light_cache->cube_tx.tex_size[0]) && (cube_len == light_cache->cube_tx.tex_size[2]) && (cube_len == light_cache->cube_len) && (mip_len == light_cache->mips_len)) { @@ -298,7 +298,7 @@ LightCache *EEVEE_lightcache_create(const int grid_len, light_cache->cube_tx.tex_size[1] = cube_size; light_cache->cube_tx.tex_size[2] = cube_len; - light_cache->mips_len = (int)(floorf(log2f(cube_size)) - MIN_CUBE_LOD_LEVEL); + light_cache->mips_len = log2_floor_u(cube_size) - MIN_CUBE_LOD_LEVEL; light_cache->vis_res = vis_size; light_cache->ref_res = cube_size; @@ -491,7 +491,7 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake) irradiance_pool_size_get(lbake->vis_res, lbake->total_irr_samples, lbake->irr_size); - lbake->ref_cube_res = OCTAHEDRAL_SIZE_FROM_CUBESIZE(lbake->rt_res); + lbake->ref_cube_res = octahedral_size_from_cubesize(lbake->rt_res); lbake->cube_prb = MEM_callocN(sizeof(LightProbe *) * lbake->cube_len, "EEVEE Cube visgroup ptr"); lbake->grid_prb = MEM_callocN(sizeof(LightProbe *) * lbake->grid_len, "EEVEE Grid visgroup ptr"); diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 7da9af55330..5e6c11833d3 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -186,7 +186,7 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) #elif defined(IRRADIANCE_HL2) int grid_res = 4; #endif - int cube_res = OCTAHEDRAL_SIZE_FROM_CUBESIZE(scene_eval->eevee.gi_cubemap_resolution); + int cube_res = octahedral_size_from_cubesize(scene_eval->eevee.gi_cubemap_resolution); int vis_res = scene_eval->eevee.gi_visibility_resolution; sldata->fallback_lightcache = EEVEE_lightcache_create( 1, 1, cube_res, vis_res, (int[3]){grid_res, grid_res, 1}); @@ -251,6 +251,8 @@ 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)); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -272,6 +274,8 @@ 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)); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -292,6 +296,8 @@ 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)); struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); DRW_shgroup_call(grp, geom, NULL); @@ -337,7 +343,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat const float *col = G_draw.block.colorBackground; /* LookDev */ - EEVEE_lookdev_cache_init(vedata, &grp, psl->probe_background, 1.0f, wo, pinfo); + EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo); /* END */ if (!grp && wo) { col = &wo->horr; @@ -360,6 +366,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat 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: @@ -403,6 +411,8 @@ 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_call_procedural_triangles(grp, NULL, cube_len * 2); } @@ -429,6 +439,8 @@ 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)); int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2; DRW_shgroup_call_procedural_triangles(shgrp, NULL, tri_count); } @@ -446,6 +458,8 @@ 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)); stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance( grp, e_data.format_probe_display_planar, DRW_cache_quad_get()); @@ -1046,7 +1060,7 @@ void EEVEE_lightbake_filter_glossy(EEVEE_ViewLayerData *sldata, float target_size = (float)GPU_texture_width(rt_color); /* Max lod used from the render target probe */ - pinfo->lod_rt_max = floorf(log2f(target_size)) - 2.0f; + pinfo->lod_rt_max = log2_floor_u(target_size) - 2.0f; pinfo->intensity_fac = intensity; /* Start fresh */ @@ -1155,7 +1169,7 @@ void EEVEE_lightbake_filter_diffuse(EEVEE_ViewLayerData *sldata, pinfo->lodfactor = bias + 0.5f * log((float)(target_size * target_size) * pinfo->samples_len_inv) / log(2); - pinfo->lod_rt_max = floorf(log2f(target_size)) - 2.0f; + pinfo->lod_rt_max = log2_floor_u(target_size) - 2.0f; #else pinfo->shres = 32; /* Less texture fetches & reduce branches */ pinfo->lod_rt_max = 2.0f; /* Improve cache reuse */ diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index 94d61a81fcc..d39d2a61657 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -57,9 +57,9 @@ static void eevee_lookdev_lightcache_delete(EEVEE_Data *vedata) } void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, - DRWShadingGroup **grp, + EEVEE_ViewLayerData *sldata, + DRWShadingGroup **r_grp, DRWPass *pass, - float background_alpha, World *UNUSED(world), EEVEE_LightProbesInfo *pinfo) { @@ -69,13 +69,27 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, EEVEE_PrivateData *g_data = stl->g_data; const DRWContextState *draw_ctx = DRW_context_state_get(); View3D *v3d = draw_ctx->v3d; + View3DShading *shading = &v3d->shading; Scene *scene = draw_ctx->scene; + const bool probe_render = pinfo != NULL; + effects->lookdev_view = NULL; if (LOOK_DEV_OVERLAY_ENABLED(v3d)) { /* Viewport / Spheres size. */ - const rcti *rect = ED_region_visible_rect(draw_ctx->ar); + const rcti *rect; + rcti fallback_rect; + if (DRW_state_is_opengl_render()) { + const float *vp_size = DRW_viewport_size_get(); + fallback_rect.xmax = vp_size[0]; + fallback_rect.ymax = vp_size[1]; + fallback_rect.xmin = fallback_rect.ymin = 0; + rect = &fallback_rect; + } + else { + rect = ED_region_visible_rect(draw_ctx->ar); + } /* Make the viewport width scale the lookdev spheres a bit. * Scale between 1000px and 2000px. */ @@ -95,21 +109,23 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, } if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) { - StudioLight *sl = BKE_studiolight_find(v3d->shading.lookdev_light, + StudioLight *sl = BKE_studiolight_find(shading->lookdev_light, STUDIOLIGHT_ORIENTATIONS_MATERIAL_MODE); if (sl && (sl->flag & STUDIOLIGHT_TYPE_WORLD)) { - GPUShader *shader = EEVEE_shaders_default_studiolight_sh_get(); - struct GPUBatch *geom = DRW_cache_fullscreen_quad_get(); - GPUTexture *tex = NULL; + GPUShader *shader = probe_render ? EEVEE_shaders_default_studiolight_sh_get() : + EEVEE_shaders_background_studiolight_sh_get(); + + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + int cube_res = octahedral_size_from_cubesize(scene_eval->eevee.gi_cubemap_resolution); /* If one of the component is missing we start from scratch. */ if ((stl->lookdev_grid_data == NULL) || (stl->lookdev_cube_data == NULL) || - (txl->lookdev_grid_tx == NULL) || (txl->lookdev_cube_tx == NULL)) { + (txl->lookdev_grid_tx == NULL) || (txl->lookdev_cube_tx == NULL) || + (g_data->light_cache && g_data->light_cache->ref_res != cube_res)) { eevee_lookdev_lightcache_delete(vedata); } if (stl->lookdev_lightcache == NULL) { - const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); #if defined(IRRADIANCE_SH_L2) int grid_res = 4; #elif defined(IRRADIANCE_CUBEMAP) @@ -117,11 +133,9 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, #elif defined(IRRADIANCE_HL2) int grid_res = 4; #endif - int cube_res = OCTAHEDRAL_SIZE_FROM_CUBESIZE(scene_eval->eevee.gi_cubemap_resolution); - int vis_res = scene_eval->eevee.gi_visibility_resolution; stl->lookdev_lightcache = EEVEE_lightcache_create( - 1, 1, cube_res, vis_res, (int[3]){grid_res, grid_res, 1}); + 1, 1, cube_res, 8, (int[3]){grid_res, grid_res, 1}); /* XXX: Fix memleak. TODO find out why. */ MEM_SAFE_FREE(stl->lookdev_cube_mips); @@ -138,49 +152,45 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, txl->lookdev_cube_tx = stl->lookdev_lightcache->cube_tx.tex; } - stl->g_data->light_cache = stl->lookdev_lightcache; - - static float background_color[4]; - UI_GetThemeColor4fv(TH_BACK, background_color); - /* XXX: Really quick conversion to avoid washed out background. - * Needs to be addressed properly (color managed using ocio). */ - srgb_to_linearrgb_v4(background_color, background_color); - - *grp = DRW_shgroup_create(shader, pass); - axis_angle_to_mat3_single( - stl->g_data->studiolight_matrix, 'Z', v3d->shading.studiolight_rot_z); - DRW_shgroup_uniform_mat3(*grp, "StudioLightMatrix", stl->g_data->studiolight_matrix); - DRW_shgroup_uniform_float_copy(*grp, "backgroundAlpha", background_alpha); - DRW_shgroup_uniform_float( - *grp, "studioLightIntensity", &v3d->shading.studiolight_intensity, 1); - - DRW_shgroup_uniform_vec3(*grp, "color", background_color, 1); - DRW_shgroup_call(*grp, geom, NULL); - if (!pinfo) { + g_data->light_cache = stl->lookdev_lightcache; + + DRWShadingGroup *grp = *r_grp = DRW_shgroup_create(shader, pass); + axis_angle_to_mat3_single(g_data->studiolight_matrix, 'Z', shading->studiolight_rot_z); + DRW_shgroup_uniform_mat3(grp, "StudioLightMatrix", g_data->studiolight_matrix); + + if (probe_render) { + DRW_shgroup_uniform_float_copy( + grp, "studioLightIntensity", shading->studiolight_intensity); + BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); + DRW_shgroup_uniform_texture(grp, "image", sl->equirect_radiance_gputexture); /* Do not fadeout when doing probe rendering, only when drawing the background */ - DRW_shgroup_uniform_float( - *grp, "studioLightBackground", &v3d->shading.studiolight_background, 1); - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE); - tex = sl->equirect_irradiance_gputexture; + DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f); } else { - DRW_shgroup_uniform_float_copy(*grp, "studioLightBackground", 1.0f); - BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE); - tex = sl->equirect_radiance_gputexture; + float background_alpha = g_data->background_alpha * shading->studiolight_background; + float studiolight_blur = powf(shading->studiolight_blur, 2.5f); + DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", background_alpha); + DRW_shgroup_uniform_float_copy(grp, "studioLightBlur", studiolight_blur); + DRW_shgroup_uniform_texture(grp, "probeCubes", txl->lookdev_cube_tx); + 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, "common_block", sldata->common_ubo); } - DRW_shgroup_uniform_texture(*grp, "image", tex); + + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); /* Do we need to recalc the lightprobes? */ if (g_data->studiolight_index != sl->index || - g_data->studiolight_rot_z != v3d->shading.studiolight_rot_z || - g_data->studiolight_intensity != v3d->shading.studiolight_intensity || + g_data->studiolight_rot_z != shading->studiolight_rot_z || + g_data->studiolight_intensity != shading->studiolight_intensity || g_data->studiolight_cubemap_res != scene->eevee.gi_cubemap_resolution || g_data->studiolight_glossy_clamp != scene->eevee.gi_glossy_clamp || g_data->studiolight_filter_quality != scene->eevee.gi_filter_quality) { stl->lookdev_lightcache->flag |= LIGHTCACHE_UPDATE_WORLD; g_data->studiolight_index = sl->index; - g_data->studiolight_rot_z = v3d->shading.studiolight_rot_z; - g_data->studiolight_intensity = v3d->shading.studiolight_intensity; + g_data->studiolight_rot_z = shading->studiolight_rot_z; + g_data->studiolight_intensity = shading->studiolight_intensity; g_data->studiolight_cubemap_res = scene->eevee.gi_cubemap_resolution; g_data->studiolight_glossy_clamp = scene->eevee.gi_glossy_clamp; g_data->studiolight_filter_quality = scene->eevee.gi_filter_quality; diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 1c0a1289ba4..0c9efeb0a16 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -25,6 +25,7 @@ #include "BLI_dynstr.h" #include "BLI_ghash.h" #include "BLI_alloca.h" +#include "BLI_math_bits.h" #include "BLI_rand.h" #include "BLI_string_utils.h" @@ -101,9 +102,37 @@ extern char datatoc_volumetric_vert_glsl[]; extern char datatoc_volumetric_geom_glsl[]; 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_ < 32; 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; \ + } \ + } \ + } + /* *********** FUNCTIONS *********** */ #if 0 /* Used only to generate the LUT values */ @@ -337,6 +366,39 @@ static char *eevee_get_volume_defines(int options) 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. */ @@ -349,7 +411,8 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, bool use_glossy, bool use_refract, bool use_ssrefraction, - bool use_alpha_blend) + bool use_alpha_blend, + eViewLayerEEVEEPassType render_pass) { LightCache *lcache = vedata->stl->g_data->light_cache; EEVEE_EffectsInfo *effects = vedata->stl->effects; @@ -360,9 +423,9 @@ 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_int_copy(shgrp, "outputSssId", 1); - 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); @@ -395,6 +458,24 @@ 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); @@ -523,6 +604,9 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, 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, @@ -600,7 +684,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, 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); @@ -635,6 +718,66 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, &fbl->update_noise_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE_LAYER(e_data.util_tex, 2)}); } + + { + /* Create RenderPass UBO */ + if (sldata->renderpass_ubo[0] == NULL) { + sldata->renderpass_data[0].renderPassDiffuse = true; + sldata->renderpass_data[0].renderPassDiffuseLight = true; + sldata->renderpass_data[0].renderPassGlossy = true; + sldata->renderpass_data[0].renderPassGlossyLight = true; + sldata->renderpass_data[0].renderPassEmit = true; + sldata->renderpass_data[0].renderPassSSSColor = false; + sldata->renderpass_data[1].renderPassDiffuse = true; + sldata->renderpass_data[1].renderPassDiffuseLight = false; + sldata->renderpass_data[1].renderPassGlossy = false; + sldata->renderpass_data[1].renderPassGlossyLight = false; + sldata->renderpass_data[1].renderPassEmit = false; + sldata->renderpass_data[1].renderPassSSSColor = true; + sldata->renderpass_data[2].renderPassDiffuse = true; + sldata->renderpass_data[2].renderPassDiffuseLight = true; + sldata->renderpass_data[2].renderPassGlossy = false; + sldata->renderpass_data[2].renderPassGlossyLight = false; + sldata->renderpass_data[2].renderPassEmit = false; + sldata->renderpass_data[2].renderPassSSSColor = false; + sldata->renderpass_data[3].renderPassDiffuse = false; + sldata->renderpass_data[3].renderPassDiffuseLight = false; + sldata->renderpass_data[3].renderPassGlossy = true; + sldata->renderpass_data[3].renderPassGlossyLight = false; + sldata->renderpass_data[3].renderPassEmit = false; + sldata->renderpass_data[3].renderPassSSSColor = false; + sldata->renderpass_data[4].renderPassDiffuse = false; + sldata->renderpass_data[4].renderPassDiffuseLight = false; + sldata->renderpass_data[4].renderPassGlossy = true; + sldata->renderpass_data[4].renderPassGlossyLight = true; + sldata->renderpass_data[4].renderPassEmit = false; + sldata->renderpass_data[4].renderPassSSSColor = false; + sldata->renderpass_data[5].renderPassDiffuse = false; + sldata->renderpass_data[5].renderPassDiffuseLight = false; + sldata->renderpass_data[5].renderPassGlossy = false; + sldata->renderpass_data[5].renderPassGlossyLight = false; + sldata->renderpass_data[5].renderPassEmit = true; + sldata->renderpass_data[5].renderPassSSSColor = 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]); + } + } + + /* HACK: EEVEE_material_world_background_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. + */ + if (g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) { + struct Scene *scene = draw_ctx->scene; + struct World *wo = scene->world; + if (wo && wo->use_nodes) { + EEVEE_material_world_background_get(scene, wo); + } + } + } } struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo) @@ -852,7 +995,17 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLaye } 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); + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + true, + true, + false, + false, + use_blend, + DEFAULT_RENDER_PASS_FLAG); return shgrp; } @@ -894,14 +1047,34 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa 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); + 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); + add_standard_uniforms(shgrp, + sldata, + vedata, + &ssr_id, + NULL, + true, + true, + false, + false, + false, + DEFAULT_RENDER_PASS_FLAG); return shgrp; } else { @@ -909,6 +1082,60 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerDa } } +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; @@ -931,8 +1158,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) const float *col = G_draw.block.colorBackground; - EEVEE_lookdev_cache_init( - vedata, &grp, psl->background_pass, stl->g_data->background_alpha, wo, NULL); + EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_pass, wo, NULL); if (!grp && wo) { col = &wo->horr; @@ -945,14 +1171,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) switch (GPU_material_status(gpumat)) { case GPU_MAT_SUCCESS: grp = DRW_shgroup_material_create(gpumat, psl->background_pass); - 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); + add_background_uniforms(grp, sldata, vedata); DRW_shgroup_call(grp, geom, NULL); break; case GPU_MAT_QUEUED: @@ -1071,7 +1290,17 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) 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); + 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); @@ -1080,12 +1309,31 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) 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); + 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); } + + { + 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; + DRW_PASS_CREATE(psl->material_accum_pass[pass_index], state); + } + } } #define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \ @@ -1109,6 +1357,7 @@ 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, @@ -1117,9 +1366,7 @@ static void material_opaque(Material *ma, EEVEE_Data *vedata, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth, - struct DRWShadingGroup **shgrp, - struct DRWShadingGroup **shgrp_depth, - struct DRWShadingGroup **shgrp_depth_clip, + struct EeveeMaterialShadingGroups *shgrps, bool holdout) { EEVEE_EffectsInfo *effects = vedata->stl->effects; @@ -1128,7 +1375,7 @@ static void material_opaque(Material *ma, 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; @@ -1143,9 +1390,7 @@ static void material_opaque(Material *ma, EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma); if (emsg) { - *shgrp = emsg->shading_grp; - *shgrp_depth = emsg->depth_grp; - *shgrp_depth_clip = emsg->depth_clip_grp; + 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) : @@ -1156,6 +1401,7 @@ static void material_opaque(Material *ma, return; } + 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}; @@ -1179,25 +1425,25 @@ static void material_opaque(Material *ma, status_mat_surface = status_mat_depth; } else if (use_ssrefract) { - *shgrp_depth = DRW_shgroup_material_create( + emsg->depth_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create( + emsg->depth_clip_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip); } else { - *shgrp_depth = DRW_shgroup_material_create( + emsg->depth_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass); - *shgrp_depth_clip = DRW_shgroup_material_create( + emsg->depth_clip_grp = DRW_shgroup_material_create( *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip); } - if (*shgrp_depth != NULL) { + 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(*shgrp_depth, + add_standard_uniforms(emsg->depth_grp, sldata, vedata, NULL, @@ -1206,8 +1452,9 @@ static void material_opaque(Material *ma, use_glossy, use_refract, false, - false); - add_standard_uniforms(*shgrp_depth_clip, + false, + DEFAULT_RENDER_PASS_FLAG); + add_standard_uniforms(emsg->depth_clip_grp, sldata, vedata, NULL, @@ -1216,11 +1463,13 @@ static void material_opaque(Material *ma, use_glossy, use_refract, false, - false); + false, + DEFAULT_RENDER_PASS_FLAG); if (ma->blend_method == MA_BM_CLIP) { - DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1); - DRW_shgroup_uniform_float(*shgrp_depth_clip, "alphaThreshold", &ma->alpha_threshold, 1); + 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); } } } @@ -1237,14 +1486,14 @@ static void material_opaque(Material *ma, use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY); use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT); - *shgrp = DRW_shgroup_material_create( + 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(*shgrp, + add_standard_uniforms(emsg->shading_grp, sldata, vedata, ssr_id, @@ -1253,7 +1502,8 @@ static void material_opaque(Material *ma, use_glossy, use_refract, use_ssrefract, - false); + false, + DEFAULT_RENDER_PASS_FLAG); if (use_sss) { struct GPUTexture *sss_tex_profile = NULL; @@ -1264,7 +1514,7 @@ static void material_opaque(Material *ma, /* 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(*shgrp, sss_id); + 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( @@ -1278,12 +1528,30 @@ static void material_opaque(Material *ma, } } } + + 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: @@ -1295,44 +1563,61 @@ static void material_opaque(Material *ma, } /* Fallback to default shader */ - if (*shgrp == NULL) { + if (emsg->shading_grp == NULL) { bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0); - *shgrp = EEVEE_default_shading_group_get( + emsg->shading_grp = EEVEE_default_shading_group_get( sldata, vedata, NULL, NULL, NULL, false, 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); + 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) } /* Fallback default depth prepass */ - if (*shgrp_depth == NULL) { + if (emsg->depth_grp == NULL) { if (use_ssrefract) { - *shgrp_depth = (do_cull) ? stl->g_data->refract_depth_shgrp_cull : - stl->g_data->refract_depth_shgrp; - *shgrp_depth_clip = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull : - stl->g_data->refract_depth_shgrp_clip; + 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; } else { - *shgrp_depth = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp; - *shgrp_depth_clip = (do_cull) ? stl->g_data->depth_shgrp_clip_cull : - stl->g_data->depth_shgrp_clip; + 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; } } - emsg = MEM_mallocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups"); - emsg->shading_grp = *shgrp; - emsg->depth_grp = *shgrp_depth; - emsg->depth_clip_grp = *shgrp_depth_clip; - BLI_ghash_insert(material_hash, ma, emsg); + memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups)); + if (store_material) { + BLI_ghash_insert(material_hash, ma, emsg); + } + else { + MEM_freeN(emsg); + } } static void material_transparent(Material *ma, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUMaterial **gpumat, - struct DRWShadingGroup **shgrp, - struct DRWShadingGroup **shgrp_depth) + struct EeveeMaterialShadingGroups *shgrps) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; @@ -1357,13 +1642,13 @@ static void material_transparent(Material *ma, /* Depth prepass */ if (use_prepass) { - *shgrp_depth = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); + shgrps->depth_grp = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass); cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL; cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; - DRW_shgroup_state_disable(*shgrp_depth, all_state); - DRW_shgroup_state_enable(*shgrp_depth, cur_state); + DRW_shgroup_state_disable(shgrps->depth_grp, all_state); + DRW_shgroup_state_enable(shgrps->depth_grp, cur_state); } if (use_gpumat) { @@ -1378,14 +1663,14 @@ static void material_transparent(Material *ma, case GPU_MAT_SUCCESS: { static int ssr_id = -1; /* TODO transparent SSR */ - *shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass); + 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(*shgrp, + add_standard_uniforms(shgrps->shading_grp, sldata, vedata, &ssr_id, @@ -1394,7 +1679,8 @@ static void material_transparent(Material *ma, use_glossy, use_refract, use_ssrefract, - use_blend); + use_blend, + DEFAULT_RENDER_PASS_FLAG); break; } case GPU_MAT_QUEUED: { @@ -1413,13 +1699,13 @@ static void material_transparent(Material *ma, } /* Fallback to default shader */ - if (*shgrp == NULL) { - *shgrp = EEVEE_default_shading_group_create( + 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(*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); + 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; @@ -1427,8 +1713,8 @@ static void material_transparent(Material *ma, cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0; /* Disable other blend modes and use the one we want. */ - DRW_shgroup_state_disable(*shgrp, all_state); - DRW_shgroup_state_enable(*shgrp, cur_state); + DRW_shgroup_state_disable(shgrps->shading_grp, all_state); + DRW_shgroup_state_enable(shgrps->shading_grp, cur_state); } /* Return correct material or empty default material if slot is empty. */ @@ -1460,10 +1746,7 @@ 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 DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len); - struct DRWShadingGroup **shgrp_depth_array = BLI_array_alloca(shgrp_depth_array, - materials_len); - struct DRWShadingGroup **shgrp_depth_clip_array = BLI_array_alloca(shgrp_depth_clip_array, + struct EeveeMaterialShadingGroups *shgrps_array = BLI_array_alloca(shgrps_array, materials_len); struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len); @@ -1472,11 +1755,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, for (int i = 0; i < materials_len; i++) { ma_array[i] = eevee_object_material_get(ob, i); + memset(&shgrps_array[i], 0, sizeof(EeveeMaterialShadingGroups)); gpumat_array[i] = NULL; gpumat_depth_array[i] = NULL; - shgrp_array[i] = NULL; - shgrp_depth_array[i] = NULL; - shgrp_depth_clip_array[i] = NULL; if (holdout) { material_opaque(ma_array[i], @@ -1485,9 +1766,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, vedata, &gpumat_array[i], &gpumat_depth_array[i], - &shgrp_array[i], - &shgrp_depth_array[i], - &shgrp_depth_clip_array[i], + &shgrps_array[i], true); continue; } @@ -1502,18 +1781,11 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, vedata, &gpumat_array[i], &gpumat_depth_array[i], - &shgrp_array[i], - &shgrp_depth_array[i], - &shgrp_depth_clip_array[i], + &shgrps_array[i], false); break; case MA_BM_BLEND: - material_transparent(ma_array[i], - sldata, - vedata, - &gpumat_array[i], - &shgrp_array[i], - &shgrp_depth_array[i]); + material_transparent(ma_array[i], sldata, vedata, &gpumat_array[i], &shgrps_array[i]); break; default: BLI_assert(0); @@ -1538,10 +1810,32 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, if (use_sculpt_pbvh) { /* Vcol is not supported in the modes that require PBVH drawing. */ - bool use_vcol = false; - DRW_shgroup_call_sculpt_with_materials(shgrp_array, ob, use_vcol); - DRW_shgroup_call_sculpt_with_materials(shgrp_depth_array, ob, use_vcol); - DRW_shgroup_call_sculpt_with_materials(shgrp_depth_clip_array, ob, use_vcol); + const bool use_vcol = false; + 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, ob, use_vcol); + + 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, ob, use_vcol); + 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, ob, use_vcol); + + 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, ob, use_vcol); + } + /* TODO(fclem): Support shadows in sculpt mode. */ } else if (mat_geom) { @@ -1565,10 +1859,16 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, oedata->ob = ob; oedata->test_data = &sldata->probes->vis_data; } - - ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i], oedata); + 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); + } /* Shadow Pass */ struct GPUMaterial *gpumat; @@ -1667,9 +1967,33 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat); if (!use_diffuse && !use_glossy && !use_refract) { - /* FIXME: Small hack to avoid issue when utilTex is needed for + /* 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 can try to bind utilTex even if not needed. */ + * This binds `utilTex` even if not needed. */ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); } @@ -1682,7 +2006,10 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, use_glossy, use_refract, false, - false); + false, + render_pass_flag); + RENDER_PASS_ITER_END(render_pass_index) + break; } case GPU_MAT_QUEUED: { @@ -1707,6 +2034,24 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, 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) } /* Shadows */ @@ -1762,3 +2107,180 @@ void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Pass DRW_draw_pass(psl->material_pass); DRW_draw_pass(psl->material_pass_cull); } + +/* -------------------------------------------------------------------- */ + +/** \name Render Passes + * \{ */ + +void EEVEE_material_renderpasses_init(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = 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 (g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) { + g_data->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; + } + 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; + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + + /* 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 ((render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) && + (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; + + 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); + } + } + } + } +} + +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_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]); + } + } + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) && + (stl->effects->enabled_effects & EFFECT_SSR)) { + EEVEE_reflection_output_accumulate(sldata, vedata); + } + } +} + +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; + + for (int bitshift = 0; bitshift < 32; bitshift++) { + eViewLayerEEVEEPassType pass_flag = (1 << bitshift); + if (pass_flag == renderpass_type) { + break; + } + if (active_material_passes & pass_flag) { + index++; + } + } + + return index; +} + +/* 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); + } + 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 c9b56a6d551..cdcfd64d995 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -114,6 +114,8 @@ 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_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 6ba518b3a28..be4dfd07ce1 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -170,6 +170,8 @@ 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_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } else { @@ -207,6 +209,8 @@ 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_call(grp, quad, NULL); DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR); @@ -215,6 +219,8 @@ 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_int(grp, "layer", &stl->effects->ao_depth_layer, 1); DRW_shgroup_call(grp, quad, NULL); @@ -227,6 +233,8 @@ 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_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 7810de289df..a2ed0a16d89 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -136,11 +136,29 @@ extern struct DrawEngineType draw_engine_eevee_type; ((v3d->shading.type == OB_RENDER) && \ ((v3d->shading.flag & V3D_SHADING_SCENE_WORLD_RENDER) == 0)))) -#define OCTAHEDRAL_SIZE_FROM_CUBESIZE(cube_size) \ - ((int)ceilf(sqrtf((cube_size * cube_size) * 6.0f))) #define MIN_CUBE_LOD_LEVEL 3 + +BLI_INLINE int octahedral_size_from_cubesize(int cube_size) +{ + int cube_pixel_count = SQUARE(cube_size) * 6.0f; + int octa_size = (int)ceilf(sqrtf(cube_pixel_count)); + int lod_count = log2_floor_u(octa_size) - MIN_CUBE_LOD_LEVEL; + /* Find lowest lod size and grow back to avoid having non matching mipsizes that would + * break trilinear interpolation. */ + octa_size /= 1 << lod_count; + octa_size *= 1 << lod_count; + return octa_size; +} + #define MAX_PLANAR_LOD_LEVEL 9 +/* All the renderpasses that use the GPUMaterial for accumulation */ +#define EEVEE_RENDERPASSES_MATERIAL \ + (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, @@ -198,6 +216,7 @@ typedef struct EEVEE_BoundBox { typedef struct EEVEE_PassList { /* Shadows */ struct DRWPass *shadow_pass; + struct DRWPass *shadow_accum_pass; /* Probes */ struct DRWPass *probe_background; @@ -220,6 +239,7 @@ typedef struct EEVEE_PassList { struct DRWPass *bloom_downsample; struct DRWPass *bloom_upsample; struct DRWPass *bloom_resolve; + struct DRWPass *bloom_accum_ps; struct DRWPass *dof_down; struct DRWPass *dof_scatter; struct DRWPass *dof_resolve; @@ -228,11 +248,11 @@ typedef struct EEVEE_PassList { struct DRWPass *volumetric_scatter_ps; struct DRWPass *volumetric_integration_ps; struct DRWPass *volumetric_resolve_ps; + struct DRWPass *volumetric_accum_ps; struct DRWPass *ssr_raytrace; struct DRWPass *ssr_resolve; struct DRWPass *sss_blur_ps; struct DRWPass *sss_resolve_ps; - struct DRWPass *sss_accum_ps; struct DRWPass *sss_translucency_ps; struct DRWPass *color_downsample_ps; struct DRWPass *color_downsample_cube_ps; @@ -264,6 +284,7 @@ typedef struct EEVEE_PassList { 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; struct DRWPass *transparent_pass; struct DRWPass *background_pass; @@ -281,6 +302,9 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *bloom_blit_fb; struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP]; struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP - 1]; + struct GPUFrameBuffer *bloom_pass_accum_fb; + struct GPUFrameBuffer *shadow_accum_fb; + struct GPUFrameBuffer *ssr_accum_fb; struct GPUFrameBuffer *sss_blur_fb; struct GPUFrameBuffer *sss_blit_fb; struct GPUFrameBuffer *sss_resolve_fb; @@ -292,9 +316,11 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *volumetric_fb; struct GPUFrameBuffer *volumetric_scat_fb; struct GPUFrameBuffer *volumetric_integ_fb; + struct GPUFrameBuffer *volumetric_accum_fb; struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *refract_fb; struct GPUFrameBuffer *mist_accum_fb; + struct GPUFrameBuffer *material_accum_fb; struct GPUFrameBuffer *renderpass_fb; struct GPUFrameBuffer *ao_accum_fb; struct GPUFrameBuffer *velocity_resolve_fb; @@ -320,8 +346,11 @@ typedef struct EEVEE_TextureList { struct GPUTexture *color_post; /* R16_G16_B16 */ struct GPUTexture *mist_accum; struct GPUTexture *ao_accum; - struct GPUTexture *sss_dir_accum; - struct GPUTexture *sss_col_accum; + struct GPUTexture *sss_accum; + struct GPUTexture *material_accum[MAX_MATERIAL_RENDER_PASSES]; + struct GPUTexture *bloom_accum; + struct GPUTexture *ssr_accum; + struct GPUTexture *shadow_accum; struct GPUTexture *refract_color; struct GPUTexture *taa_history; @@ -333,6 +362,8 @@ typedef struct EEVEE_TextureList { struct GPUTexture *volume_transmit; struct GPUTexture *volume_scatter_history; struct GPUTexture *volume_transmit_history; + struct GPUTexture *volume_scatter_accum; + struct GPUTexture *volume_transmittance_accum; struct GPUTexture *lookdev_grid_tx; struct GPUTexture *lookdev_cube_tx; @@ -361,6 +392,17 @@ typedef struct EEVEE_StorageList { LightCacheTexture *lookdev_cube_mips; } EEVEE_StorageList; +/* ************ RENDERPASS UBO ************* */ +typedef struct EEVEE_RenderPassData { + int renderPassDiffuse; + int renderPassDiffuseLight; + int renderPassGlossy; + int renderPassGlossyLight; + int renderPassEmit; + int renderPassSSSColor; + int _pad[2]; +} EEVEE_RenderPassData; + /* ************ LIGHT UBO ************* */ typedef struct EEVEE_Light { float position[3], invsqrdist; @@ -408,6 +450,7 @@ BLI_STATIC_ASSERT_ALIGN(EEVEE_Light, 16) BLI_STATIC_ASSERT_ALIGN(EEVEE_Shadow, 16) BLI_STATIC_ASSERT_ALIGN(EEVEE_ShadowCube, 16) BLI_STATIC_ASSERT_ALIGN(EEVEE_ShadowCascade, 16) +BLI_STATIC_ASSERT_ALIGN(EEVEE_RenderPassData, 16) BLI_STATIC_ASSERT(sizeof(EEVEE_Shadow) * MAX_SHADOW + sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE + @@ -708,6 +751,10 @@ typedef struct EEVEE_ViewLayerData { struct GPUUniformBuffer *grid_ubo; 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]; + /* Common Uniform Buffer */ struct EEVEE_CommonUniformBuffer common_data; struct GPUUniformBuffer *common_ubo; @@ -759,6 +806,7 @@ 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; @@ -803,12 +851,17 @@ typedef struct EEVEE_PrivateData { /* Renderpasses */ /* Bitmask containing the active render_passes */ - eScenePassType render_passes; + eViewLayerEEVEEPassType render_passes; /* Uniform references that are referenced inside the `renderpass_pass`. They are updated * to reuse the drawing pass and the shading group. */ int renderpass_type; + int renderpass_postprocess; int renderpass_current_sample; GPUTexture *renderpass_input; + GPUTexture *renderpass_col_input; + GPUTexture *renderpass_light_input; + /* The number of active material based render passes */ + uint render_passes_material_count; /** For rendering shadows. */ struct DRWView *cube_views[6]; @@ -860,11 +913,20 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, 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); /* 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); @@ -896,6 +958,8 @@ void EEVEE_shadows_draw_cascades(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView *view, int cascade_index); +void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_shadow_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_shadows_free(void); /* eevee_sampling.c */ @@ -923,6 +987,7 @@ 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_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); @@ -995,6 +1060,8 @@ void EEVEE_depth_of_field_free(void); int EEVEE_bloom_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_bloom_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_bloom_draw(EEVEE_Data *vedata); +void EEVEE_bloom_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_bloom_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_bloom_free(void); /* eevee_occlusion.c */ @@ -1016,6 +1083,11 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_refraction_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_reflection_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_reflection_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); +void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); + void EEVEE_screen_raytrace_free(void); /* eevee_subsurface.c */ @@ -1055,10 +1127,12 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata); void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); -void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + bool post_effect); void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - eScenePassType renderpass_type); + eViewLayerEEVEEPassType renderpass_type); void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_renderpasses_draw_debug(EEVEE_Data *vedata); void EEVEE_renderpasses_free(void); @@ -1087,6 +1161,8 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) void EEVEE_volumes_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_volumes_resolve(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples); +void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_volumes_free_smoke_textures(void); void EEVEE_volumes_free(void); @@ -1104,7 +1180,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_effects_free(void); /* eevee_render.c */ -void EEVEE_render_init(EEVEE_Data *vedata, +bool EEVEE_render_init(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph); void EEVEE_render_cache(void *vedata, @@ -1121,9 +1197,9 @@ void EEVEE_render_update_passes(struct RenderEngine *engine, /** eevee_lookdev.c */ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata, DRWShadingGroup **grp, DRWPass *pass, - float background_alpha, struct World *world, EEVEE_LightProbesInfo *pinfo); void EEVEE_lookdev_draw(EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 063510d51e6..3a5d9e96b80 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -46,7 +46,8 @@ #include "eevee_private.h" -void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph) +/* Return true if init properly. */ +bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph) { EEVEE_Data *vedata = (EEVEE_Data *)ved; EEVEE_StorageList *stl = vedata->stl; @@ -106,7 +107,7 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * max_dim); RE_engine_set_error_message(engine, error_msg); G.is_break = true; - return; + return false; } /* XXX overriding viewport size. Simplify things but is not really 100% safe. */ @@ -168,6 +169,8 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * EEVEE_subsurface_cache_init(sldata, vedata); EEVEE_temporal_sampling_cache_init(sldata, vedata); EEVEE_volumes_cache_init(sldata, vedata); + + return true; } /* Used by light cache. in this case engine is NULL. */ @@ -230,6 +233,9 @@ static void eevee_render_color_result(RenderLayer *rl, EEVEE_Data *vedata) { RenderPass *rp = RE_pass_find_by_name(rl, render_pass_name, viewname); + if (rp == NULL) { + return; + } GPU_framebuffer_bind(framebuffer); GPU_framebuffer_read_color(framebuffer, vedata->stl->g_data->overscan_pixels + rect->xmin, @@ -251,35 +257,6 @@ static void eevee_render_result_combined(RenderLayer *rl, rl, viewname, rect, RE_PASSNAME_COMBINED, 4, vedata->stl->effects->final_fb, vedata); } -static void eevee_render_result_subsurface(RenderLayer *rl, - const char *viewname, - const rcti *rect, - EEVEE_Data *vedata, - EEVEE_ViewLayerData *sldata) -{ - if (vedata->fbl->sss_accum_fb == NULL) { - /* SSS is not enabled. */ - return; - } - - if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_COLOR) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_COLOR); - eevee_render_color_result( - rl, viewname, rect, RE_PASSNAME_SUBSURFACE_COLOR, 3, vedata->fbl->renderpass_fb, vedata); - } - - if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_DIRECT) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_DIRECT); - eevee_render_color_result( - rl, viewname, rect, RE_PASSNAME_SUBSURFACE_DIRECT, 3, vedata->fbl->renderpass_fb, vedata); - } - - if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { - /* Do nothing as all the lighting is in the direct pass. - * TODO : Separate Direct from indirect lighting. */ - } -} - static void eevee_render_result_normal(RenderLayer *rl, const char *viewname, const rcti *rect, @@ -293,8 +270,8 @@ static void eevee_render_result_normal(RenderLayer *rl, return; } - if ((vedata->stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_NORMAL); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_NORMAL) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_NORMAL); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_NORMAL, 3, vedata->fbl->renderpass_fb, vedata); } @@ -313,8 +290,8 @@ static void eevee_render_result_z(RenderLayer *rl, return; } - if ((vedata->stl->g_data->render_passes & SCE_PASS_Z) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_Z); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_Z) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_Z); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_Z, 1, vedata->fbl->renderpass_fb, vedata); } @@ -326,31 +303,142 @@ static void eevee_render_result_mist(RenderLayer *rl, EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) { - if ((vedata->stl->g_data->render_passes & SCE_PASS_MIST) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_MIST); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_MIST) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_MIST); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_MIST, 1, vedata->fbl->renderpass_fb, vedata); } } +static void eevee_render_result_shadow(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_SHADOW) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_SHADOW); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SHADOW, 3, vedata->fbl->renderpass_fb, vedata); + } +} + static void eevee_render_result_occlusion(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) { - if (vedata->fbl->ao_accum_fb == NULL) { + if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) == 0) { /* AO is not enabled. */ return; } - if ((vedata->stl->g_data->render_passes & SCE_PASS_AO) != 0) { - EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_AO); + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_AO) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_AO); eevee_render_color_result( rl, viewname, rect, RE_PASSNAME_AO, 3, vedata->fbl->renderpass_fb, vedata); } } +static void eevee_render_result_bloom(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + if ((vedata->stl->effects->enabled_effects & EFFECT_BLOOM) == 0) { + /* Bloom is not enabled. */ + return; + } + + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_BLOOM) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_BLOOM); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_BLOOM, 3, vedata->fbl->renderpass_fb, vedata); + } +} + +#define EEVEE_RENDER_RESULT_MATERIAL_PASS(pass_name, eevee_pass_type) \ + if ((vedata->stl->g_data->render_passes & EEVEE_RENDER_PASS_##eevee_pass_type) != 0) { \ + EEVEE_renderpasses_postprocess(sldata, vedata, EEVEE_RENDER_PASS_##eevee_pass_type); \ + eevee_render_color_result( \ + rl, viewname, rect, RE_PASSNAME_##pass_name, 3, vedata->fbl->renderpass_fb, vedata); \ + } + +static void eevee_render_result_diffuse_color(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(DIFFUSE_COLOR, DIFFUSE_COLOR) +} + +static void eevee_render_result_diffuse_direct(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(DIFFUSE_DIRECT, DIFFUSE_LIGHT) +} + +static void eevee_render_result_specular_color(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(GLOSSY_COLOR, SPECULAR_COLOR) +} + +static void eevee_render_result_specular_direct(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(GLOSSY_DIRECT, SPECULAR_LIGHT) +} + +static void eevee_render_result_emission(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(EMIT, EMIT) +} + +static void eevee_render_result_environment(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(ENVIRONMENT, ENVIRONMENT) +} + +static void eevee_render_result_volume_scatter(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_SCATTER, VOLUME_SCATTER) +} +static void eevee_render_result_volume_transmittance(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *sldata) +{ + EEVEE_RENDER_RESULT_MATERIAL_PASS(VOLUME_TRANSMITTANCE, VOLUME_TRANSMITTANCE) +} + +#undef EEVEE_RENDER_RESULT_MATERIAL_PASS + static void eevee_render_draw_background(EEVEE_Data *vedata) { EEVEE_FramebufferList *fbl = vedata->fbl; @@ -508,7 +596,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl /* Volumetrics Resolve Opaque */ EEVEE_volumes_resolve(sldata, vedata); /* Subsurface output, Occlusion output, Mist output */ - EEVEE_renderpasses_output_accumulate(sldata, vedata); + EEVEE_renderpasses_output_accumulate(sldata, vedata, false); /* Transparent */ GPU_framebuffer_texture_attach(fbl->main_color_fb, dtxl->depth, 0, 0); GPU_framebuffer_bind(fbl->main_color_fb); @@ -527,9 +615,18 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl } eevee_render_result_combined(rl, viewname, rect, vedata, sldata); - eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata); eevee_render_result_mist(rl, viewname, rect, vedata, sldata); eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata); + eevee_render_result_shadow(rl, viewname, rect, vedata, sldata); + eevee_render_result_diffuse_color(rl, viewname, rect, vedata, sldata); + eevee_render_result_diffuse_direct(rl, viewname, rect, vedata, sldata); + eevee_render_result_specular_color(rl, viewname, rect, vedata, sldata); + eevee_render_result_specular_direct(rl, viewname, rect, vedata, sldata); + eevee_render_result_emission(rl, viewname, rect, vedata, sldata); + eevee_render_result_environment(rl, viewname, rect, vedata, sldata); + eevee_render_result_bloom(rl, viewname, rect, vedata, sldata); + eevee_render_result_volume_scatter(rl, viewname, rect, vedata, sldata); + eevee_render_result_volume_transmittance(rl, viewname, rect, vedata, sldata); /* Restore original viewport size. */ DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]}); @@ -537,29 +634,35 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer) { - int type; - RE_engine_register_pass(engine, scene, view_layer, RE_PASSNAME_COMBINED, 4, "RGBA", SOCK_RGBA); -#define CHECK_PASS(name, channels, chanid) \ +#define CHECK_PASS_LEGACY(name, type, channels, chanid) \ if (view_layer->passflag & (SCE_PASS_##name)) { \ - if (channels == 4) \ - type = SOCK_RGBA; \ - else if (channels == 3) \ - type = SOCK_VECTOR; \ - else \ - type = SOCK_FLOAT; \ + RE_engine_register_pass( \ + engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \ + } \ + ((void)0) +#define CHECK_PASS_EEVEE(name, type, channels, chanid) \ + if (view_layer->eevee.render_passes & (EEVEE_RENDER_PASS_##name)) { \ RE_engine_register_pass( \ engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \ } \ ((void)0) - CHECK_PASS(Z, 1, "Z"); - CHECK_PASS(MIST, 1, "Z"); - CHECK_PASS(NORMAL, 3, "XYZ"); - CHECK_PASS(AO, 3, "RGB"); - CHECK_PASS(SUBSURFACE_COLOR, 3, "RGB"); - CHECK_PASS(SUBSURFACE_DIRECT, 3, "RGB"); + CHECK_PASS_LEGACY(Z, SOCK_FLOAT, 1, "Z"); + CHECK_PASS_LEGACY(MIST, SOCK_FLOAT, 1, "Z"); + CHECK_PASS_LEGACY(NORMAL, SOCK_VECTOR, 3, "XYZ"); + CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(DIFFUSE_COLOR, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(DIFFUSE_DIRECT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(GLOSSY_COLOR, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_EEVEE(VOLUME_SCATTER, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_EEVEE(VOLUME_TRANSMITTANCE, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_EEVEE(BLOOM, SOCK_RGBA, 3, "RGB"); #undef CHECK_PASS } diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 44a6c41e170..2f9e8f3d555 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -42,19 +42,35 @@ static struct { struct GPUShader *postprocess_sh; } e_data = {NULL}; /* Engine data */ +typedef enum eRenderPassPostProcessType { + PASS_POST_UNDEFINED = 0, + PASS_POST_ACCUMULATED_COLOR = 1, + PASS_POST_ACCUMULATED_LIGHT = 2, + PASS_POST_ACCUMULATED_VALUE = 3, + PASS_POST_DEPTH = 4, + PASS_POST_AO = 5, + PASS_POST_NORMAL = 6, + PASS_POST_TWO_LIGHT_BUFFERS = 7, +} eRenderPassPostProcessType; + /* bitmask containing all renderpasses that need post-processing */ #define EEVEE_RENDERPASSES_WITH_POST_PROCESSING \ - (SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | SCE_PASS_SUBSURFACE_COLOR | \ - SCE_PASS_SUBSURFACE_DIRECT) - -#define EEVEE_RENDERPASSES_SUBSURFACE \ - (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_INDIRECT) + (EEVEE_RENDER_PASS_Z | EEVEE_RENDER_PASS_MIST | EEVEE_RENDER_PASS_NORMAL | \ + EEVEE_RENDER_PASS_AO | EEVEE_RENDER_PASS_BLOOM | EEVEE_RENDER_PASS_VOLUME_SCATTER | \ + EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_SHADOW | \ + EEVEE_RENDERPASSES_MATERIAL) -#define EEVEE_RENDERPASSES_ALL (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | SCE_PASS_COMBINED) +#define EEVEE_RENDERPASSES_ALL \ + (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | EEVEE_RENDER_PASS_COMBINED) -#define EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE (SCE_PASS_Z | SCE_PASS_NORMAL) +#define EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE \ + (EEVEE_RENDER_PASS_Z | EEVEE_RENDER_PASS_NORMAL) -#define EEVEE_RENDERPASSES_COLOR_PASS (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT) +#define EEVEE_RENDERPASSES_COLOR_PASS \ + (EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_EMIT | \ + EEVEE_RENDER_PASS_BLOOM) +#define EEVEE_RENDERPASSES_LIGHT_PASS \ + (EEVEE_RENDER_PASS_DIFFUSE_LIGHT | EEVEE_RENDER_PASS_SPECULAR_LIGHT) bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata) { @@ -75,8 +91,33 @@ void EEVEE_renderpasses_init(EEVEE_Data *vedata) g_data->render_passes = v3d->shading.render_pass; } else { - g_data->render_passes = (view_layer->passflag & EEVEE_RENDERPASSES_ALL) | SCE_PASS_COMBINED; + eViewLayerEEVEEPassType enabled_render_passes = view_layer->eevee.render_passes; + +#define ENABLE_FROM_LEGACY(name_legacy, name_eevee) \ + SET_FLAG_FROM_TEST(enabled_render_passes, \ + (view_layer->passflag & SCE_PASS_##name_legacy) != 0, \ + EEVEE_RENDER_PASS_##name_eevee); + + ENABLE_FROM_LEGACY(Z, Z) + ENABLE_FROM_LEGACY(MIST, MIST) + ENABLE_FROM_LEGACY(NORMAL, NORMAL) + ENABLE_FROM_LEGACY(SHADOW, SHADOW) + ENABLE_FROM_LEGACY(AO, AO) + ENABLE_FROM_LEGACY(EMIT, EMIT) + ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT) + ENABLE_FROM_LEGACY(DIFFUSE_COLOR, DIFFUSE_COLOR) + ENABLE_FROM_LEGACY(GLOSSY_COLOR, SPECULAR_COLOR) + ENABLE_FROM_LEGACY(DIFFUSE_DIRECT, DIFFUSE_LIGHT) + ENABLE_FROM_LEGACY(GLOSSY_DIRECT, SPECULAR_LIGHT) + + ENABLE_FROM_LEGACY(ENVIRONMENT, ENVIRONMENT) + +#undef ENABLE_FROM_LEGACY + g_data->render_passes = (enabled_render_passes & EEVEE_RENDERPASSES_ALL) | + EEVEE_RENDER_PASS_COMBINED; } + + EEVEE_material_renderpasses_init(vedata); } void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, @@ -87,6 +128,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, EEVEE_TextureList *txl = vedata->txl; EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -106,33 +148,54 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, /* Should be enough to store the data needs for a single pass. * Some passes will use less, but it is only relevant for final renderings and - * when renderpasses other than `SCE_PASS_COMBINED` are requested */ + * when renderpasses other than `EEVEE_RENDER_PASS_COMBINED` are requested */ DRW_texture_ensure_fullscreen_2d(&txl->renderpass, GPU_RGBA16F, 0); GPU_framebuffer_ensure_config(&fbl->renderpass_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->renderpass)}); - if ((g_data->render_passes & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { - EEVEE_subsurface_output_init(sldata, vedata, tot_samples); + if ((g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL) != 0) { + EEVEE_material_output_init(sldata, vedata, tot_samples); } - if ((g_data->render_passes & SCE_PASS_MIST) != 0) { + if ((g_data->render_passes & EEVEE_RENDER_PASS_MIST) != 0) { EEVEE_mist_output_init(sldata, vedata); } + if ((g_data->render_passes & EEVEE_RENDER_PASS_SHADOW) != 0) { + EEVEE_shadow_output_init(sldata, vedata, tot_samples); + } - if ((g_data->render_passes & SCE_PASS_AO) != 0) { + if ((g_data->render_passes & EEVEE_RENDER_PASS_AO) != 0) { EEVEE_occlusion_output_init(sldata, vedata, tot_samples); } + if ((g_data->render_passes & EEVEE_RENDER_PASS_BLOOM) != 0 && + (effects->enabled_effects & EFFECT_BLOOM) != 0) { + EEVEE_bloom_output_init(sldata, vedata, tot_samples); + } + + if ((g_data->render_passes & + (EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_VOLUME_SCATTER)) != 0) { + EEVEE_volumes_output_init(sldata, vedata, tot_samples); + } + /* Create Pass. */ DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.postprocess_sh, psl->renderpass_pass); /* We set a default texture as not all post processes uses the inputBuffer. */ g_data->renderpass_input = txl->color; + g_data->renderpass_col_input = txl->color; + g_data->renderpass_light_input = txl->color; DRW_shgroup_uniform_texture_ref(grp, "inputBuffer", &g_data->renderpass_input); + DRW_shgroup_uniform_texture_ref(grp, "inputColorBuffer", &g_data->renderpass_col_input); + DRW_shgroup_uniform_texture_ref( + 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_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); DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } else { @@ -152,12 +215,13 @@ 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 *UNUSED(sldata), +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - eScenePassType renderpass_type) + eViewLayerEEVEEPassType renderpass_type) { EEVEE_PassList *psl = vedata->psl; EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; EEVEE_PrivateData *g_data = stl->g_data; EEVEE_EffectsInfo *effects = stl->effects; @@ -165,51 +229,133 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata), const int current_sample = effects->taa_current_sample; g_data->renderpass_current_sample = current_sample; g_data->renderpass_type = renderpass_type; + g_data->renderpass_postprocess = PASS_POST_UNDEFINED; switch (renderpass_type) { - case SCE_PASS_AO: { + case EEVEE_RENDER_PASS_Z: { + g_data->renderpass_postprocess = PASS_POST_DEPTH; + break; + } + case EEVEE_RENDER_PASS_AO: { + g_data->renderpass_postprocess = PASS_POST_AO; g_data->renderpass_input = txl->ao_accum; break; } - case SCE_PASS_NORMAL: { + case EEVEE_RENDER_PASS_NORMAL: { + g_data->renderpass_postprocess = PASS_POST_NORMAL; g_data->renderpass_input = effects->ssr_normal_input; break; } - case SCE_PASS_MIST: { + case EEVEE_RENDER_PASS_MIST: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_VALUE; g_data->renderpass_input = txl->mist_accum; break; } - case SCE_PASS_SUBSURFACE_DIRECT: { - g_data->renderpass_input = txl->sss_dir_accum; + case EEVEE_RENDER_PASS_VOLUME_SCATTER: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->volume_scatter_accum; + break; + } + case EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->volume_transmittance_accum; + break; + } + case EEVEE_RENDER_PASS_SHADOW: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_VALUE; + g_data->renderpass_input = txl->shadow_accum; break; } - case SCE_PASS_SUBSURFACE_COLOR: { - g_data->renderpass_input = txl->sss_col_accum; + case EEVEE_RENDER_PASS_DIFFUSE_COLOR: + case EEVEE_RENDER_PASS_SPECULAR_COLOR: + case EEVEE_RENDER_PASS_ENVIRONMENT: + 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]; + 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]; + 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; + } + else { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; + } + break; + } + 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]; + 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; + } + else { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT; + } + break; + } + case EEVEE_RENDER_PASS_BLOOM: { + g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR; + g_data->renderpass_input = txl->bloom_accum; + g_data->renderpass_current_sample = 1; break; } default: { break; } } - GPU_framebuffer_bind(vedata->fbl->renderpass_fb); + GPU_framebuffer_bind(fbl->renderpass_fb); DRW_draw_pass(psl->renderpass_pass); } -void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + bool post_effect) { EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; - eScenePassType render_pass = stl->g_data->render_passes; + eViewLayerEEVEEPassType render_pass = stl->g_data->render_passes; - if ((render_pass & SCE_PASS_MIST) != 0) { - EEVEE_mist_output_accumulate(sldata, vedata); - } - if ((effects->enabled_effects & EFFECT_SSS) && - (render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { - EEVEE_subsurface_output_accumulate(sldata, vedata); + if (!post_effect) { + 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); + } + if ((render_pass & EEVEE_RENDER_PASS_SHADOW) != 0) { + EEVEE_shadow_output_accumulate(sldata, vedata); + } + if ((render_pass & EEVEE_RENDERPASSES_MATERIAL) != 0) { + EEVEE_material_output_accumulate(sldata, vedata); + } + if ((render_pass & + (EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE | EEVEE_RENDER_PASS_VOLUME_SCATTER)) != 0) { + EEVEE_volumes_output_accumulate(sldata, vedata); + } } - if ((render_pass & SCE_PASS_AO) != 0) { - EEVEE_occlusion_output_accumulate(sldata, vedata); + else { + if ((render_pass & EEVEE_RENDER_PASS_BLOOM) != 0 && + (effects->enabled_effects & EFFECT_BLOOM) != 0) { + EEVEE_bloom_output_accumulate(sldata, vedata); + } } } @@ -220,7 +366,13 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); - eScenePassType render_pass = stl->g_data->render_passes; + + /* We can only draw a single renderpass. Lightpasses also select their color pass (a second + pass). We mask the light pass when a light pass is selected. */ + const eViewLayerEEVEEPassType render_pass = + ((stl->g_data->render_passes & EEVEE_RENDERPASSES_LIGHT_PASS) != 0) ? + (stl->g_data->render_passes & EEVEE_RENDERPASSES_LIGHT_PASS) : + stl->g_data->render_passes; const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); @@ -229,14 +381,14 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_state_is_opengl_render(); UNUSED_VARS(needs_color_transfer); - /* When SSS isn't available, but the pass is requested, we mark it as invalid */ - if ((render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0 && - (effects->enabled_effects & EFFECT_SSS) == 0) { + if ((render_pass & EEVEE_RENDER_PASS_BLOOM) != 0 && + (effects->enabled_effects & EFFECT_BLOOM) == 0) { is_valid = false; } /* When SSS isn't available, but the pass is requested, we mark it as invalid */ - if ((render_pass & SCE_PASS_AO) != 0 && (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0) { + if ((render_pass & EEVEE_RENDER_PASS_AO) != 0 && + (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0) { is_valid = false; } @@ -254,7 +406,7 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } else { /* Draw state is not valid for this pass, clear the buffer */ - static float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + static float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f}; GPU_framebuffer_bind(dfbl->default_fb); GPU_framebuffer_clear_color(dfbl->default_fb, clear_color); } diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 591ca31017c..d231edf1383 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -235,6 +235,8 @@ 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)); if (!effects->reflection_trace_full) { DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1); } @@ -255,6 +257,8 @@ 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_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()); @@ -335,6 +339,43 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v } } +void EEVEE_reflection_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + uint tot_samples) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + const eGPUTextureFormat texture_format = (tot_samples > 256) ? GPU_RGBA32F : GPU_RGBA16F; + DRW_texture_ensure_fullscreen_2d(&txl->ssr_accum, texture_format, 0); + + GPU_framebuffer_ensure_config(&fbl->ssr_accum_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ssr_accum)}); + + /* Clear texture. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->ssr_accum_fb); + GPU_framebuffer_clear_color(fbl->ssr_accum_fb, clear); + } +} + +void EEVEE_reflection_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + + if (stl->g_data->valid_double_buffer) { + GPU_framebuffer_bind(fbl->ssr_accum_fb); + DRW_draw_pass(psl->ssr_resolve); + } +} + void EEVEE_screen_raytrace_free(void) { for (int i = 0; i < SSR_MAX_SHADER; i++) { diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index 34a3e723161..2d91e4bb4bd 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -44,6 +44,7 @@ static struct { /* Probes */ struct GPUShader *probe_default_sh; struct GPUShader *probe_default_studiolight_sh; + struct GPUShader *probe_background_studiolight_sh; struct GPUShader *probe_grid_display_sh; struct GPUShader *probe_cube_display_sh; struct GPUShader *probe_planar_display_sh; @@ -191,6 +192,27 @@ GPUShader *EEVEE_shaders_default_studiolight_sh_get(void) return e_data.probe_default_studiolight_sh; } +GPUShader *EEVEE_shaders_background_studiolight_sh_get(void) +{ + if (e_data.probe_background_studiolight_sh == NULL) { + char *frag_str = BLI_string_joinN(datatoc_octahedron_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_default_world_frag_glsl); + + e_data.probe_background_studiolight_sh = DRW_shader_create_with_lib( + datatoc_background_vert_glsl, + NULL, + frag_str, + datatoc_common_view_lib_glsl, + "#define LOOKDEV_BG\n" SHADER_DEFINES); + + MEM_freeN(frag_str); + } + return e_data.probe_background_studiolight_sh; +} + GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void) { if (e_data.probe_cube_display_sh == NULL) { @@ -299,6 +321,7 @@ void EEVEE_shaders_free(void) DRW_SHADER_FREE_SAFE(e_data.probe_grid_fill_sh); DRW_SHADER_FREE_SAFE(e_data.probe_planar_downsample_sh); DRW_SHADER_FREE_SAFE(e_data.probe_default_studiolight_sh); + DRW_SHADER_FREE_SAFE(e_data.probe_background_studiolight_sh); DRW_SHADER_FREE_SAFE(e_data.probe_grid_display_sh); DRW_SHADER_FREE_SAFE(e_data.probe_cube_display_sh); DRW_SHADER_FREE_SAFE(e_data.probe_planar_display_sh); diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index 1776f535237..f5b98d464dd 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -21,6 +21,7 @@ */ #include "BLI_sys_types.h" /* bool */ +#include "BLI_string_utils.h" // #include "BLI_dynstr.h" // #include "BLI_rand.h" @@ -35,11 +36,17 @@ static struct { struct GPUShader *shadow_sh; + struct GPUShader *shadow_accum_sh; } e_data = {NULL}; /* Engine data */ extern char datatoc_shadow_vert_glsl[]; extern char datatoc_shadow_frag_glsl[]; +extern char datatoc_shadow_accum_frag_glsl[]; extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_lights_lib_glsl[]; +extern char datatoc_raytrace_lib_glsl[]; void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh) { @@ -65,6 +72,18 @@ void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata) NULL); } + if (!e_data.shadow_accum_sh) { + char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_raytrace_lib_glsl, + datatoc_lights_lib_glsl, + datatoc_shadow_accum_frag_glsl); + + e_data.shadow_accum_sh = DRW_shader_create_fullscreen(frag_str, SHADER_DEFINES); + MEM_freeN(frag_str); + } + if (!sldata->lights) { sldata->lights = MEM_callocN(sizeof(EEVEE_LightsInfo), "EEVEE_LightsInfo"); sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL); @@ -170,6 +189,8 @@ void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata, 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) { @@ -406,7 +427,75 @@ void EEVEE_shadows_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWView } } +/* -------------------------------------------------------------------- */ + +/** \name Render Passes + * \{ */ + +void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint UNUSED(tot_samples)) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + const eGPUTextureFormat texture_format = GPU_R32F; + DRW_texture_ensure_fullscreen_2d(&txl->shadow_accum, texture_format, 0); + + GPU_framebuffer_ensure_config(&fbl->shadow_accum_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->shadow_accum)}); + + /* Clear texture. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->shadow_accum_fb); + GPU_framebuffer_clear_color(fbl->shadow_accum_fb, clear); + } + + /* Create Pass and shgroup. */ + DRW_PASS_CREATE(psl->shadow_accum_pass, + DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_BLEND_ADD_FULL); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_accum_sh, psl->shadow_accum_pass); + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + 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, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); + DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool); + DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool); + + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); +} + +void EEVEE_shadow_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + + if (fbl->shadow_accum_fb != NULL) { + GPU_framebuffer_bind(fbl->shadow_accum_fb); + DRW_draw_pass(psl->shadow_accum_pass); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +/* \} */ + void EEVEE_shadows_free(void) { DRW_SHADER_FREE_SAFE(e_data.shadow_sh); + DRW_SHADER_FREE_SAFE(e_data.shadow_accum_sh); } diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c index 32045e12a1c..1fd8d818b33 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c +++ b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c @@ -120,11 +120,6 @@ static void frustum_min_bounding_sphere(const float corners[8][3], #endif } -BLI_INLINE float lerp(float t, float a, float b) -{ - return ((a) + (t) * ((b) - (a))); -} - static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, DRWView *view, @@ -254,11 +249,11 @@ static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo, for (int c = 1; c < cascade_nbr; c++) { /* View Space */ - float linear_split = lerp(((float)(c) / (float)cascade_nbr), csm_start, csm_end); - float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr); + float linear_split = interpf(csm_end, csm_start, c / (float)cascade_nbr); + float exp_split = csm_start * powf(csm_end / csm_start, c / (float)cascade_nbr); if (is_persp) { - csm_data->split_start[c] = lerp(cascade_exponent, linear_split, exp_split); + csm_data->split_start[c] = interpf(exp_split, linear_split, cascade_exponent); } else { csm_data->split_start[c] = linear_split; @@ -266,10 +261,10 @@ static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo, csm_data->split_end[c - 1] = csm_data->split_start[c]; /* Add some overlap for smooth transition */ - csm_data->split_start[c] = lerp(cascade_fade, - csm_data->split_end[c - 1], - (c > 1) ? csm_data->split_end[c - 2] : - csm_data->split_start[0]); + csm_data->split_start[c] = interpf((c > 1) ? csm_data->split_end[c - 2] : + csm_data->split_start[0], + csm_data->split_end[c - 1], + cascade_fade); /* NDC Space */ { @@ -298,7 +293,8 @@ static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo, /* Set last cascade split fade distance into the first split_start. */ float prev_split = (cascade_nbr > 1) ? csm_data->split_end[cascade_nbr - 2] : csm_data->split_start[0]; - csm_data->split_start[0] = lerp(cascade_fade, csm_data->split_end[cascade_nbr - 1], prev_split); + csm_data->split_start[0] = interpf( + prev_split, csm_data->split_end[cascade_nbr - 1], cascade_fade); /* For each cascade */ for (int c = 0; c < cascade_nbr; c++) { diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index e94fc903694..98e799acb5e 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -33,7 +33,7 @@ #include "GPU_extensions.h" static struct { - struct GPUShader *sss_sh[4]; + struct GPUShader *sss_sh[3]; } e_data = {{NULL}}; /* Engine data */ extern char datatoc_common_view_lib_glsl[]; @@ -64,8 +64,7 @@ static void eevee_create_shader_subsurface(void) e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n"); e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"); - e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define RESULT_ACCUM\n"); - e_data.sss_sh[3] = DRW_shader_create_fullscreen(frag_translucent_str, + e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_translucent_str, "#define EEVEE_TRANSLUCENCY\n" SHADER_DEFINES); MEM_freeN(frag_translucent_str); @@ -85,9 +84,10 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold; } -void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_EffectsInfo *effects = vedata->stl->effects; + EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); @@ -138,72 +138,64 @@ void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(effects->sss_irradiance), GPU_ATTACHMENT_TEXTURE(effects->sss_radius)}); + if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0) { + EEVEE_subsurface_output_init(sldata, vedata, 0); + } + else { + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb); + txl->sss_accum = NULL; + } } else { /* Cleanup to release memory */ GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_blur_fb); GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_resolve_fb); GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_clear_fb); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb); effects->sss_stencil = NULL; effects->sss_blur = NULL; effects->sss_irradiance = NULL; effects->sss_radius = NULL; + txl->sss_accum = NULL; } } -static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp) -{ - DRW_shgroup_stencil_mask(shgrp, 255); -} - void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, - uint tot_samples) + uint UNUSED(tot_samples)) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; - if (effects->enabled_effects & EFFECT_SSS) { - const eGPUTextureFormat texture_format_light = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; - const eGPUTextureFormat texture_format_color = (tot_samples > 512) ? GPU_RGBA32F : GPU_RGBA16F; - DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, texture_format_light, 0); - DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, texture_format_color, 0); - - GPUTexture *stencil_tex = effects->sss_stencil; + const eGPUTextureFormat texture_format_light = GPU_RGBA32F; + const bool texture_created = txl->sss_accum == NULL; + DRW_texture_ensure_fullscreen_2d(&txl->sss_accum, texture_format_light, 0); - if (GPU_depth_blitting_workaround()) { - DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - /* Blitting stencil buffer does not work on macOS + Radeon Pro. - * Blit depth instead and use sss_stencil's depth as depth texture, - * and dtxl->depth as stencil mask. */ - stencil_tex = dtxl->depth; - } + GPUTexture *stencil_tex = effects->sss_stencil; - GPU_framebuffer_ensure_config(&fbl->sss_accum_fb, - {GPU_ATTACHMENT_TEXTURE(stencil_tex), - GPU_ATTACHMENT_TEXTURE(txl->sss_dir_accum), - GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)}); + if (GPU_depth_blitting_workaround()) { + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + /* Blitting stencil buffer does not work on macOS + Radeon Pro. + * Blit depth instead and use sss_stencil's depth as depth texture, + * and dtxl->depth as stencil mask. */ + stencil_tex = dtxl->depth; + } - /* Clear texture. */ - if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { - float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPU_framebuffer_bind(fbl->sss_accum_fb); - GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); - } + GPU_framebuffer_ensure_config( + &fbl->sss_accum_fb, + {GPU_ATTACHMENT_TEXTURE(stencil_tex), GPU_ATTACHMENT_TEXTURE(txl->sss_accum)}); - /* Make the opaque refraction pass mask the sss. */ - DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | - DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS; - DRW_pass_state_set(vedata->psl->refract_pass, state); - DRW_pass_foreach_shgroup(vedata->psl->refract_pass, &set_shgrp_stencil, NULL); - } - else { - /* Cleanup to release memory */ - DRW_TEXTURE_FREE_SAFE(txl->sss_dir_accum); - DRW_TEXTURE_FREE_SAFE(txl->sss_col_accum); - GPU_FRAMEBUFFER_FREE_SAFE(fbl->sss_accum_fb); + /* Clear texture. + * Due to the late initialization of the SSS it can happen that the `taa_current_sample` is + * already higher than one. This is noticeable when loading a file that has the diffuse light + * pass in look dev mode active. `texture_created` will make sure that newly created textures + * are cleared. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1 || texture_created) { + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(fbl->sss_accum_fb); + GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); } } @@ -222,7 +214,6 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_STENCIL_EQUAL; DRW_PASS_CREATE(psl->sss_blur_ps, state); DRW_PASS_CREATE(psl->sss_resolve_ps, state | DRW_STATE_BLEND_ADD); - DRW_PASS_CREATE(psl->sss_accum_ps, state | DRW_STATE_BLEND_ADD); DRW_PASS_CREATE(psl->sss_translucency_ps, state | DRW_STATE_BLEND_ADD); } @@ -245,6 +236,8 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, 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); @@ -256,22 +249,10 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, 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); - - if ((stl->g_data->render_passes & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT)) != - 0) { - grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_accum_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_stencil_mask(grp, sss_id); - DRW_shgroup_call(grp, quad, NULL); - } } void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata, @@ -287,7 +268,7 @@ void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata, struct GPUBatch *quad = DRW_cache_fullscreen_quad_get(); GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[3], psl->sss_translucency_ps); + 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); @@ -298,6 +279,8 @@ void EEVEE_subsurface_translucency_add_pass(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_stencil_mask(grp, sss_id); DRW_shgroup_call(grp, quad, NULL); } @@ -408,11 +391,11 @@ void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEV if (((effects->enabled_effects & EFFECT_SSS) != 0) && (fbl->sss_accum_fb != NULL)) { /* Copy stencil channel, could be avoided (see EEVEE_subsurface_init) */ - GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_blur_fb, 0, GPU_STENCIL_BIT); + GPU_framebuffer_blit(fbl->main_fb, 0, fbl->sss_accum_fb, 0, GPU_STENCIL_BIT); /* Only do vertical pass + Resolve */ GPU_framebuffer_bind(fbl->sss_accum_fb); - DRW_draw_pass(psl->sss_accum_ps); + DRW_draw_pass(psl->sss_resolve_ps); /* Restore */ GPU_framebuffer_bind(fbl->main_fb); @@ -424,5 +407,4 @@ void EEVEE_subsurface_free(void) DRW_SHADER_FREE_SAFE(e_data.sss_sh[0]); DRW_SHADER_FREE_SAFE(e_data.sss_sh[1]); DRW_SHADER_FREE_SAFE(e_data.sss_sh[2]); - DRW_SHADER_FREE_SAFE(e_data.sss_sh[3]); } diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 093a4780a97..bd77279eb4a 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -290,6 +290,8 @@ 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)); 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 7026894076a..456673c92fa 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -54,6 +54,7 @@ static struct { struct GPUShader *scatter_with_lights_sh; struct GPUShader *volumetric_integration_sh; struct GPUShader *volumetric_resolve_sh; + struct GPUShader *volumetric_accum_sh; GPUTexture *depth_src; @@ -73,6 +74,7 @@ extern char datatoc_common_view_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; extern char datatoc_irradiance_lib_glsl[]; extern char datatoc_lights_lib_glsl[]; +extern char datatoc_volumetric_accum_frag_glsl[]; extern char datatoc_volumetric_frag_glsl[]; extern char datatoc_volumetric_geom_glsl[]; extern char datatoc_volumetric_vert_glsl[]; @@ -136,6 +138,8 @@ static void eevee_create_shader_volumes(void) datatoc_volumetric_resolve_frag_glsl, e_data.volumetric_common_lib, NULL); + e_data.volumetric_accum_sh = DRW_shader_create_fullscreen(datatoc_volumetric_accum_frag_glsl, + NULL); float color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, color); @@ -359,6 +363,8 @@ 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)); /* Fix principle volumetric not working with world materials. */ DRW_shgroup_uniform_texture(grp, "sampdensity", e_data.dummy_density); @@ -375,6 +381,8 @@ 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_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); } @@ -430,8 +438,12 @@ 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, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_block( + grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata)); DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1); DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1); @@ -522,6 +534,8 @@ 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_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]); @@ -530,6 +544,8 @@ 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_call_procedural_triangles( grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]); @@ -540,6 +556,8 @@ 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_call_procedural_triangles(grp, NULL, 1); } @@ -729,4 +747,75 @@ void EEVEE_volumes_free(void) DRW_SHADER_FREE_SAFE(e_data.scatter_with_lights_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_accum_sh); +} + +/* -------------------------------------------------------------------- */ + +/** \name Render Passes + * \{ */ + +void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = stl->effects; + + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + /* Create FrameBuffer. */ + + /* Should be enough precision for many samples. */ + const eGPUTextureFormat texture_format_accum = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; + DRW_texture_ensure_fullscreen_2d(&txl->volume_scatter_accum, texture_format_accum, 0); + DRW_texture_ensure_fullscreen_2d(&txl->volume_transmittance_accum, texture_format_accum, 0); + + GPU_framebuffer_ensure_config(&fbl->volumetric_accum_fb, + {GPU_ATTACHMENT_NONE, + GPU_ATTACHMENT_TEXTURE(txl->volume_scatter_accum), + GPU_ATTACHMENT_TEXTURE(txl->volume_transmittance_accum)}); + + /* Clear texture. */ + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->volumetric_accum_fb); + GPU_framebuffer_clear_color(fbl->volumetric_accum_fb, clear); + } + + /* Create Pass and shgroup. */ + DRW_PASS_CREATE(psl->volumetric_accum_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL); + DRWShadingGroup *grp = NULL; + if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { + grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_accum_ps); + DRW_shgroup_uniform_texture_ref(grp, "inScattering", &txl->volume_scatter); + 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)); + } + else { + /* There is no volumetrics in the scene. Use a shader to fill the accum textures with a default + * value. */ + grp = DRW_shgroup_create(e_data.volumetric_accum_sh, psl->volumetric_accum_ps); + } + DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); } + +void EEVEE_volumes_output_accumulate(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_PassList *psl = vedata->psl; + + if (fbl->volumetric_accum_fb != NULL) { + /* Accum pass */ + GPU_framebuffer_bind(fbl->volumetric_accum_fb); + DRW_draw_pass(psl->volumetric_accum_ps); + + /* Restore */ + GPU_framebuffer_bind(fbl->main_fb); + } +} + +/* \} */ 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 c4f815b5dd4..c3518198805 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -85,6 +85,37 @@ struct ShadowCascadeData { #define sh_shadow_vec shadow_vec_id.xyz #define sh_tex_index shadow_vec_id.w +/* ------ Render Passes ----- */ +layout(std140) uniform renderpass_block +{ + bool renderPassDiffuse; + bool renderPassDiffuseLight; + bool renderPassGlossy; + bool renderPassGlossyLight; + bool renderPassEmit; + bool renderPassSSSColor; +}; + +vec3 render_pass_diffuse_mask(vec3 diffuse_color, vec3 diffuse_light) +{ + return renderPassDiffuse ? (renderPassDiffuseLight ? diffuse_light : diffuse_color) : vec3(0.0); +} + +vec3 render_pass_sss_mask(vec3 sss_color) +{ + return renderPassSSSColor ? sss_color : vec3(0.0); +} + +vec3 render_pass_glossy_mask(vec3 specular_color, vec3 specular_light) +{ + return renderPassGlossy ? (renderPassGlossyLight ? specular_light : specular_color) : vec3(0.0); +} + +vec3 render_pass_emission_mask(vec3 emission_light) +{ + return renderPassEmit ? emission_light : vec3(0.0); +} + /* ------- Convenience functions --------- */ vec3 mul(mat3 m, vec3 v) @@ -833,11 +864,12 @@ void closure_load_sss_data( cl.sss_radius = radius; cl.sss_albedo = sss_albedo; cl.flag |= CLOSURE_SSS_FLAG; + cl.radiance += render_pass_diffuse_mask(sss_albedo, vec3(0)); } else # endif { - cl.radiance += sss_irradiance * sss_albedo; + cl.radiance += render_pass_diffuse_mask(sss_albedo, sss_irradiance * sss_albedo); } } diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl index a031ed193b6..1014b25033a 100644 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -34,7 +34,8 @@ Closure nodetree_exec(void) eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, true, out_diff, out_spec, ssr_spec); Closure cl = CLOSURE_DEFAULT; - cl.radiance = out_spec + out_diff * albedo; + cl.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) + + render_pass_diffuse_mask(albedo, out_diff * albedo); closure_load_ssr_data(ssr_spec, roughness, N, viewCameraVec, 1, cl); #ifdef LOOKDEV diff --git a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl index 41e103609f3..1faa02fd354 100644 --- a/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_world_frag.glsl @@ -4,11 +4,12 @@ uniform vec3 color; out vec4 FragColor; -#ifdef LOOKDEV +#if defined(LOOKDEV_BG) || defined(LOOKDEV) + uniform mat3 StudioLightMatrix; uniform sampler2D image; -uniform float studioLightBackground = 1.0; uniform float studioLightIntensity = 1.0; +uniform float studioLightBlur = 0.0; in vec3 viewPosition; # define M_PI 3.14159265358979323846 @@ -49,11 +50,17 @@ vec4 node_tex_environment_equirectangular(vec3 co, sampler2D ima) void main() { vec3 background_color; -#ifdef LOOKDEV + +#if defined(LOOKDEV_BG) + vec3 worldvec = background_transform_to_world(viewPosition); + background_color = probe_evaluate_world_spec(worldvec, studioLightBlur).rgb; + background_color *= studioLightIntensity; + +#elif defined(LOOKDEV) vec3 worldvec = background_transform_to_world(viewPosition); background_color = node_tex_environment_equirectangular(StudioLightMatrix * worldvec, image).rgb; background_color *= studioLightIntensity; - background_color = mix(color, background_color, studioLightBackground); + #else background_color = color; #endif diff --git a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl index 299cb2094c1..18f92c0dd33 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_bloom_frag.glsl @@ -40,6 +40,7 @@ uniform float sampleScale; /* Step Resolve */ uniform vec3 bloomColor; +uniform bool bloomAddBase; in vec4 uvcoordsvar; @@ -201,9 +202,9 @@ vec4 step_resolve(void) #else vec3 blur = upsample_filter(sourceBuffer, uvcoordsvar.xy, sourceBufferTexelSize); #endif - vec4 base = textureLod(baseBuffer, uvcoordsvar.xy, 0.0); - vec3 cout = base.rgb + blur * bloomColor; - return vec4(cout, base.a); + vec3 base = bloomAddBase ? textureLod(baseBuffer, uvcoordsvar.xy, 0.0).rgb : vec3(0.0); + vec3 cout = base + blur * bloomColor; + return vec4(cout, 1.0); } void main(void) diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl index 1241cf0e387..e9da49c9eb9 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -20,13 +20,7 @@ uniform sampler2DArray utilTex; # define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) #endif /* UTIL_TEX */ -#ifdef RESULT_ACCUM -/* Render Passes Accumulation */ -layout(location = 0) out vec4 sssDirect; -layout(location = 1) out vec4 sssColor; -#else layout(location = 0) out vec4 sssRadiance; -#endif float get_view_z_from_depth(float depth) { @@ -87,10 +81,7 @@ void main(void) accum += kernel[i].rgb * mix(color, sss_irradiance, s); } -#ifdef RESULT_ACCUM - sssDirect = vec4(accum, 1.0); - sssColor = vec4(texture(sssAlbedo, uvs).rgb, 1.0); -#elif defined(FIRST_PASS) +#if defined(FIRST_PASS) sssRadiance = vec4(accum, 1.0); #else /* SECOND_PASS */ sssRadiance = vec4(accum * texture(sssAlbedo, uvs).rgb, 1.0); diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl index 6427f02ed25..3b9d0a8f2bc 100644 --- a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -173,19 +173,17 @@ float light_attenuation(LightData ld, vec4 l_vector) return vis; } -float light_visibility(LightData ld, - vec3 W, +float light_shadowing(LightData ld, + vec3 W, #ifndef VOLUMETRICS - vec3 viewPosition, - float tracing_depth, - vec3 true_normal, - float rand_x, - const bool use_contact_shadows, + vec3 viewPosition, + float tracing_depth, + vec3 true_normal, + float rand_x, + const bool use_contact_shadows, #endif - vec4 l_vector) + float vis) { - float vis = light_attenuation(ld, l_vector); - #if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW) /* shadowing */ if (ld.l_shadowid >= 0.0 && vis > 0.001) { @@ -236,6 +234,30 @@ float light_visibility(LightData ld, return vis; } +float light_visibility(LightData ld, + vec3 W, +#ifndef VOLUMETRICS + vec3 viewPosition, + float tracing_depth, + vec3 true_normal, + float rand_x, + const bool use_contact_shadows, +#endif + vec4 l_vector) +{ + float l_atten = light_attenuation(ld, l_vector); + return light_shadowing(ld, + W, +#ifndef VOLUMETRICS + viewPosition, + tracing_depth, + true_normal, + rand_x, + use_contact_shadows, +#endif + l_atten); +} + #ifdef USE_LTC float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) { diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl index 35bfb411cb9..5214301bc03 100644 --- a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -1,15 +1,17 @@ -#define SCE_PASS_Z (1 << 1) -#define SCE_PASS_AO (1 << 6) -#define SCE_PASS_NORMAL (1 << 8) -#define SCE_PASS_MIST (1 << 14) -#define SCE_PASS_SUBSURFACE_DIRECT (1 << 28) -#define SCE_PASS_SUBSURFACE_COLOR (1 << 30) +#define PASS_POST_UNDEFINED 0 +#define PASS_POST_ACCUMULATED_COLOR 1 +#define PASS_POST_ACCUMULATED_LIGHT 2 +#define PASS_POST_ACCUMULATED_VALUE 3 +#define PASS_POST_DEPTH 4 +#define PASS_POST_AO 5 +#define PASS_POST_NORMAL 6 +#define PASS_POST_TWO_LIGHT_BUFFERS 7 -#define ACCUMULATED_COLOR_PASSES (SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_COLOR) -#define ACCUMULATED_VALUE_PASSES (SCE_PASS_MIST) -uniform int renderpassType; +uniform int postProcessType; uniform int currentSample; uniform sampler2D inputBuffer; +uniform sampler2D inputSecondLightBuffer; +uniform sampler2D inputColorBuffer; out vec4 fragColor; @@ -17,7 +19,7 @@ void main() { ivec2 texel = ivec2(gl_FragCoord.xy); - if (renderpassType == SCE_PASS_Z) { + if (postProcessType == PASS_POST_DEPTH) { float depth = texelFetch(depthBuffer, texel, 0).r; if (depth == 1.0f) { depth = 1e10; @@ -27,17 +29,15 @@ void main() } fragColor.r = depth; } - - else if (renderpassType == SCE_PASS_AO) { + else if (postProcessType == PASS_POST_AO) { float ao_accum = texelFetch(inputBuffer, texel, 0).r; fragColor = vec4(vec3(min(1.0, ao_accum / currentSample)), 1.0); } - - else if (renderpassType == SCE_PASS_NORMAL) { + else if (postProcessType == PASS_POST_NORMAL) { float depth = texelFetch(depthBuffer, texel, 0).r; vec2 encoded_normal = texelFetch(inputBuffer, texel, 0).rg; - /* decode the normals only when they are valid. otherwise the result buffer will be filled with - * NaN's */ + /* decode the normals only when they are valid. otherwise the result buffer will be filled + * with NaN's */ if (depth != 1.0 && any(notEqual(encoded_normal, vec2(0.0)))) { vec3 decoded_normal = normal_decode(texelFetch(inputBuffer, texel, 0).rg, vec3(0.0)); vec3 world_normal = mat3(ViewMatrixInverse) * decoded_normal; @@ -47,18 +47,55 @@ void main() fragColor = vec4(0.0, 0.0, 0.0, 1.0); } } - - else if ((renderpassType & ACCUMULATED_VALUE_PASSES) != 0) { + else if (postProcessType == PASS_POST_ACCUMULATED_VALUE) { float accumulated_value = texelFetch(inputBuffer, texel, 0).r; fragColor = vec4(vec3(accumulated_value / currentSample), 1.0); } - - else if ((renderpassType & ACCUMULATED_COLOR_PASSES) != 0) { + else if (postProcessType == PASS_POST_ACCUMULATED_COLOR) { vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; fragColor = vec4(accumulated_color / currentSample, 1.0); } + else if (postProcessType == PASS_POST_ACCUMULATED_LIGHT) { + vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb; + vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; + /* Fix INF in the case a color component is 0.0 */ + if (accumulated_color.r == 0.0) { + accumulated_color.r = 1.0; + accumulated_light.r = 0.0; + } + if (accumulated_color.g == 0.0) { + accumulated_color.g = 1.0; + accumulated_light.g = 0.0; + } + if (accumulated_color.b == 0.0) { + accumulated_color.b = 1.0; + accumulated_light.b = 0.0; + } + fragColor = vec4(accumulated_light / accumulated_color, 1.0); + } + else if (postProcessType == PASS_POST_TWO_LIGHT_BUFFERS) { + vec3 accumulated_light = texelFetch(inputBuffer, texel, 0).rgb + + texelFetch(inputSecondLightBuffer, texel, 0).rgb; + vec3 accumulated_color = texelFetch(inputColorBuffer, texel, 0).rgb; + + /* Fix INF in the case a color component is 0.0 */ + if (accumulated_color.r == 0.0) { + accumulated_color.r = 1.0; + accumulated_light.r = 0.0; + } + if (accumulated_color.g == 0.0) { + accumulated_color.g = 1.0; + accumulated_light.g = 0.0; + } + if (accumulated_color.b == 0.0) { + accumulated_color.b = 1.0; + accumulated_light.b = 0.0; + } + fragColor = vec4(accumulated_light / accumulated_color, 1.0); + } else { + /* Output error color: Unknown how to post process this pass. */ fragColor = vec4(1.0, 0.0, 1.0, 1.0); } } diff --git a/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl new file mode 100644 index 00000000000..fa02bee45b7 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_accum_frag.glsl @@ -0,0 +1,58 @@ + +out vec4 fragColor; + +#ifndef UTIL_TEX +# define UTIL_TEX +uniform sampler2DArray utilTex; +# define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ + +void main() +{ + if (laNumLight == 0) { + /* Early exit: No lights in scene */ + fragColor.r = 0.0; + return; + } + + ivec2 texel = ivec2(gl_FragCoord.xy); + float depth = texelFetch(depthBuffer, texel, 0).r; + if (depth == 1.0f) { + /* Early exit background does not receive shadows */ + fragColor.r = 1.0; + return; + } + + vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xy; + vec2 uvs = saturate(gl_FragCoord.xy * texel_size); + vec4 rand = texelfetch_noise_tex(texel); + + float accum_light = 0.0; + float tracing_depth = depth; + /* Constant bias (due to depth buffer precision) */ + /* Magic numbers for 24bits of precision. + * From http://terathon.com/gdc07_lengyel.pdf (slide 26) */ + tracing_depth -= mix(2.4e-7, 4.8e-7, depth); + /* Convert to view Z. */ + tracing_depth = get_view_z_from_depth(tracing_depth); + + vec3 viewPosition = get_view_space_from_depth(uvs, depth); + vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); + + vec3 true_normal = normalize(cross(dFdx(viewPosition), dFdy(viewPosition))); + + for (int i = 0; i < MAX_LIGHT && i < laNumLight; i++) { + LightData ld = lights_data[i]; + + vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */ + l_vector.xyz = ld.l_position - worldPosition; + l_vector.w = length(l_vector.xyz); + + float l_vis = light_shadowing( + ld, worldPosition, viewPosition, tracing_depth, true_normal, rand.x, true, 1.0); + + accum_light += l_vis; + } + + fragColor.r = accum_light / float(laNumLight); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_accum_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_accum_frag.glsl new file mode 100644 index 00000000000..1b6a7b33f42 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/volumetric_accum_frag.glsl @@ -0,0 +1,11 @@ + +/* This shader is used to add default values to the volume accum textures. + * so it looks similar (transmittance = 1, scattering = 0) */ +layout(location = 0, index = 0) out vec4 FragColor0; +layout(location = 0, index = 1) out vec4 FragColor1; + +void main() +{ + FragColor0 = vec4(0.0); + FragColor1 = vec4(1.0); +} diff --git a/source/blender/draw/engines/overlay/overlay_antialiasing.c b/source/blender/draw/engines/overlay/overlay_antialiasing.c index b8e39e3f0a9..0b7637aa098 100644 --- a/source/blender/draw/engines/overlay/overlay_antialiasing.c +++ b/source/blender/draw/engines/overlay/overlay_antialiasing.c @@ -68,7 +68,10 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata) DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); /* Small texture which will have very small impact on rendertime. */ - DRW_texture_ensure_2d(&txl->dummy_depth_tx, 1, 1, GPU_DEPTH_COMPONENT24, 0); + if (txl->dummy_depth_tx == NULL) { + float pixel[1] = {1.0f}; + txl->dummy_depth_tx = DRW_texture_create_2d(1, 1, GPU_DEPTH_COMPONENT24, 0, pixel); + } if (!DRW_state_is_fbo()) { pd->antialiasing.enabled = false; @@ -110,6 +113,16 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata) GPU_ATTACHMENT_TEXTURE(color_tex), GPU_ATTACHMENT_TEXTURE(line_tex), }); + + if (pd->xray_enabled) { + DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0); + + GPU_framebuffer_ensure_config(&fbl->overlay_xray_depth_copy_fb, + { + GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), + GPU_ATTACHMENT_NONE, + }); + } } void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata) @@ -137,6 +150,18 @@ void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_texture_ref(grp, "lineTex", &txl->overlay_line_tx); DRW_shgroup_call_procedural_triangles(grp, NULL, 1); } + + /* A bit out of place... not related to antialiasing. */ + if (pd->xray_enabled) { + DRW_PASS_CREATE(psl->xray_fade_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_MUL); + + sh = OVERLAY_shader_xray_fade(); + grp = DRW_shgroup_create(sh, psl->xray_fade_ps); + DRW_shgroup_uniform_texture_ref(grp, "depthTex", &dtxl->depth); + DRW_shgroup_uniform_texture_ref(grp, "xrayDepthTex", &txl->temp_depth_tx); + DRW_shgroup_uniform_float_copy(grp, "opacity", 1.0f - pd->xray_opacity); + DRW_shgroup_call_procedural_triangles(grp, NULL, 1); + } } void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata) @@ -187,6 +212,34 @@ void OVERLAY_antialiasing_start(OVERLAY_Data *vedata) } } +void OVERLAY_xray_depth_copy(OVERLAY_Data *vedata) +{ + OVERLAY_FramebufferList *fbl = vedata->fbl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + + if (DRW_state_is_fbo() && pd->xray_enabled) { + if (pd->xray_opacity > 0.0f) { + /* We copy the depth of the rendered geometry to be able to compare to the overlays depth. */ + GPU_framebuffer_blit( + fbl->overlay_default_fb, 0, fbl->overlay_xray_depth_copy_fb, 0, GPU_DEPTH_BIT); + } + /* We then clear to not occlude the overlays directly. */ + GPU_framebuffer_bind(fbl->overlay_default_fb); + GPU_framebuffer_clear_depth(fbl->overlay_default_fb, 1.0f); + } +} + +void OVERLAY_xray_fade_draw(OVERLAY_Data *vedata) +{ + OVERLAY_PassList *psl = vedata->psl; + OVERLAY_PrivateData *pd = vedata->stl->pd; + + if (DRW_state_is_fbo() && pd->xray_enabled && pd->xray_opacity > 0.0f) { + /* Partially occlude overlays using the geometry depth pass. */ + DRW_draw_pass(psl->xray_fade_ps); + } +} + void OVERLAY_antialiasing_end(OVERLAY_Data *vedata) { OVERLAY_PassList *psl = vedata->psl; diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c index c41fc274f17..a8d2c4c6cf0 100644 --- a/source/blender/draw/engines/overlay/overlay_engine.c +++ b/source/blender/draw/engines/overlay/overlay_engine.c @@ -75,6 +75,7 @@ static void OVERLAY_engine_init(void *vedata) pd->wireframe_mode = (v3d->shading.type == OB_WIRE); pd->clipping_state = RV3D_CLIPPING_ENABLED(v3d, rv3d) ? DRW_STATE_CLIP_PLANES : 0; + pd->xray_opacity = XRAY_ALPHA(v3d); pd->xray_enabled = XRAY_ACTIVE(v3d); pd->xray_enabled_and_not_wire = pd->xray_enabled && v3d->shading.type > OB_WIRE; pd->clear_in_front = (v3d->shading.type != OB_SOLID); @@ -410,6 +411,7 @@ static void OVERLAY_draw_scene(void *vedata) } OVERLAY_outline_draw(vedata); + OVERLAY_xray_depth_copy(vedata); if (DRW_state_is_fbo()) { GPU_framebuffer_bind(fbl->overlay_default_fb); @@ -433,6 +435,7 @@ static void OVERLAY_draw_scene(void *vedata) GPU_framebuffer_bind(fbl->overlay_color_only_fb); } + OVERLAY_xray_fade_draw(vedata); OVERLAY_grid_draw(vedata); if (DRW_state_is_fbo()) { diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h index 4cd3877f21f..185df723301 100644 --- a/source/blender/draw/engines/overlay/overlay_private.h +++ b/source/blender/draw/engines/overlay/overlay_private.h @@ -35,6 +35,7 @@ typedef struct OVERLAY_FramebufferList { struct GPUFrameBuffer *overlay_color_only_fb; struct GPUFrameBuffer *overlay_in_front_fb; struct GPUFrameBuffer *overlay_line_in_front_fb; + struct GPUFrameBuffer *overlay_xray_depth_copy_fb; struct GPUFrameBuffer *outlines_prepass_fb; struct GPUFrameBuffer *outlines_resolve_fb; } OVERLAY_FramebufferList; @@ -94,6 +95,7 @@ typedef struct OVERLAY_PassList { DRWPass *sculpt_mask_ps; DRWPass *wireframe_ps; DRWPass *wireframe_xray_ps; + DRWPass *xray_fade_ps; } OVERLAY_PassList; /* Data used by GLSL shader. To be used as UBO. */ @@ -272,6 +274,7 @@ typedef struct OVERLAY_PrivateData { bool hide_overlays; bool xray_enabled; bool xray_enabled_and_not_wire; + float xray_opacity; short v3d_flag; /* TODO move to View3DOverlay */ short v3d_gridflag; /* TODO move to View3DOverlay */ DRWState clipping_state; @@ -391,6 +394,8 @@ void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata); void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata); void OVERLAY_antialiasing_start(OVERLAY_Data *vedata); void OVERLAY_antialiasing_end(OVERLAY_Data *vedata); +void OVERLAY_xray_fade_draw(OVERLAY_Data *vedata); +void OVERLAY_xray_depth_copy(OVERLAY_Data *vedata); bool OVERLAY_armature_is_pose_mode(Object *ob, const struct DRWContextState *draw_ctx); void OVERLAY_armature_cache_init(OVERLAY_Data *vedata); @@ -579,6 +584,7 @@ GPUShader *OVERLAY_shader_sculpt_mask(void); GPUShader *OVERLAY_shader_volume_velocity(bool use_needle); GPUShader *OVERLAY_shader_wireframe(void); GPUShader *OVERLAY_shader_wireframe_select(void); +GPUShader *OVERLAY_shader_xray_fade(void); OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void); diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index 6b8c5b23e58..d33ef239198 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -103,6 +103,7 @@ extern char datatoc_sculpt_mask_vert_glsl[]; extern char datatoc_volume_velocity_vert_glsl[]; extern char datatoc_wireframe_vert_glsl[]; extern char datatoc_wireframe_frag_glsl[]; +extern char datatoc_xray_fade_frag_glsl[]; extern char datatoc_gpu_shader_depth_only_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; @@ -179,6 +180,7 @@ typedef struct OVERLAY_Shaders { GPUShader *volume_velocity_sh; GPUShader *wireframe_select; GPUShader *wireframe; + GPUShader *xray_fade; } OVERLAY_Shaders; static struct { @@ -1265,6 +1267,18 @@ GPUShader *OVERLAY_shader_wireframe(void) return sh_data->wireframe; } +GPUShader *OVERLAY_shader_xray_fade(void) +{ + OVERLAY_Shaders *sh_data = &e_data.sh_data[0]; + if (!sh_data->xray_fade) { + sh_data->xray_fade = GPU_shader_create_from_arrays({ + .vert = (const char *[]){datatoc_common_fullscreen_vert_glsl, NULL}, + .frag = (const char *[]){datatoc_xray_fade_frag_glsl, NULL}, + }); + } + return sh_data->xray_fade; +} + static OVERLAY_InstanceFormats g_formats = {NULL}; OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void) diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl index 8759ef80888..768b0596d17 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_vert.glsl @@ -26,6 +26,14 @@ bool test_occlusion() return ndc.z > texture(depthTex, ndc.xy).r; } +vec3 non_linear_blend_color(vec3 col1, vec3 col2, float fac) +{ + col1 = pow(col1, vec3(1.0 / 2.2)); + col2 = pow(col2, vec3(1.0 / 2.2)); + vec3 col = mix(col1, col2, fac); + return pow(col, vec3(2.2)); +} + void main() { GPU_INTEL_VERTEX_SHADER_WORKAROUND @@ -88,7 +96,8 @@ void main() float facing = dot(view_vec, view_normal); facing = 1.0 - abs(facing) * 0.2; - finalColor.rgb = mix(colorEditMeshMiddle.rgb, finalColor.rgb, facing); + /* Do interpolation in a non-linear space to have a better visual result. */ + finalColor.rgb = non_linear_blend_color(colorEditMeshMiddle.rgb, finalColor.rgb, facing); #endif #ifdef USE_WORLD_CLIP_PLANES diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl index 4d705a4ee2b..31ac9a2b181 100644 --- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl @@ -138,9 +138,12 @@ void main() facing = clamp(abs(facing), 0.0, 1.0); - vec3 final_front_col = mix(rim_col, wire_col, 0.4); - vec3 final_rim_col = mix(rim_col, wire_col, 0.1); - finalColor = mix(final_rim_col, final_front_col, facing); + /* Do interpolation in a non-linear space to have a better visual result. */ + rim_col = pow(rim_col, vec3(1.0 / 2.2)); + wire_col = pow(wire_col, vec3(1.0 / 2.2)); + vec3 final_front_col = mix(rim_col, wire_col, 0.35); + finalColor = mix(rim_col, final_front_col, facing); + finalColor = pow(finalColor, vec3(2.2)); #endif /* Cull flat edges below threshold. */ diff --git a/source/blender/draw/engines/overlay/shaders/xray_fade_frag.glsl b/source/blender/draw/engines/overlay/shaders/xray_fade_frag.glsl new file mode 100644 index 00000000000..b6a5c8d895c --- /dev/null +++ b/source/blender/draw/engines/overlay/shaders/xray_fade_frag.glsl @@ -0,0 +1,15 @@ + +uniform sampler2D depthTex; +uniform sampler2D xrayDepthTex; +uniform float opacity; + +in vec4 uvcoordsvar; + +out vec4 fragColor; + +void main() +{ + float depth = texture(depthTex, uvcoordsvar.xy).r; + float depth_xray = texture(xrayDepthTex, uvcoordsvar.xy).r; + fragColor = vec4((depth < 1.0 && depth > depth_xray) ? opacity : 1.0); +} diff --git a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl deleted file mode 100644 index c9711e9c7d6..00000000000 --- a/source/blender/draw/engines/workbench/shaders/workbench_checkerboard_depth_frag.glsl +++ /dev/null @@ -1,38 +0,0 @@ - -/* 4x4 bayer matrix. */ -#define P(x) ((x + 0.5) * (1.0 / 16.0)) -const vec4 dither_mat[4] = vec4[4](vec4(P(0.0), P(8.0), P(2.0), P(10.0)), - vec4(P(12.0), P(4.0), P(14.0), P(6.0)), - vec4(P(3.0), P(11.0), P(1.0), P(9.0)), - vec4(P(15.0), P(7.0), P(13.0), P(5.0))); - -uniform float threshold = 0.5; -uniform float offset = 0.0; - -/* Noise dithering pattern - * 0 - Bayer matrix - * 1 - Interlieved gradient noise - */ -#define NOISE 1 - -void main() -{ -#if NOISE == 0 - ivec2 tx = ivec2(gl_FragCoord.xy) % 4; - float noise = dither_mat[tx.x][tx.y]; -#elif NOISE == 1 - /* Interlieved gradient noise by Jorge Jimenez - * http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare */ - float noise = fract( - offset + 52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y)); -#else -# error -#endif - - if (noise > threshold) { - discard; - } - else { - gl_FragDepth = 1.0; - } -} diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index b8e9f9b8428..f2cc7cdf573 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -56,7 +56,6 @@ static struct { WORKBENCH_FORWARD_Shaders sh_data[GPU_SHADER_CFG_LEN]; struct GPUShader *composite_sh_cache[2]; - struct GPUShader *checker_depth_sh; struct GPUTexture *object_id_tx; /* ref only, not alloced */ struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */ @@ -72,7 +71,6 @@ extern char datatoc_workbench_forward_composite_frag_glsl[]; extern char datatoc_workbench_forward_depth_frag_glsl[]; extern char datatoc_workbench_forward_transparent_accum_frag_glsl[]; extern char datatoc_workbench_data_lib_glsl[]; -extern char datatoc_workbench_checkerboard_depth_frag_glsl[]; extern char datatoc_workbench_object_outline_lib_glsl[]; extern char datatoc_workbench_curvature_lib_glsl[]; extern char datatoc_workbench_prepass_vert_glsl[]; @@ -349,11 +347,6 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) WORKBENCH_PrivateData *wpd = stl->g_data; workbench_private_data_init(wpd); - if (!e_data.checker_depth_sh) { - e_data.checker_depth_sh = DRW_shader_create_fullscreen( - datatoc_workbench_checkerboard_depth_frag_glsl, NULL); - } - workbench_forward_outline_shaders_ensure(wpd, draw_ctx->sh_cfg); workbench_volume_engine_init(); @@ -438,31 +431,9 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) workbench_aa_create_pass(vedata, &e_data.transparent_accum_tx); } - /* Checker Depth */ - { - static float noise_offset = 0.0f; - float blend_threshold = 0.0f; - - if (DRW_state_is_image_render()) { - /* TODO: Should be based on the number of samples used for render. */ - noise_offset = fmodf(noise_offset + 1.0f / 8.0f, 1.0f); - } - - if (XRAY_ENABLED(wpd)) { - blend_threshold = 1.0f - XRAY_ALPHA(wpd) * 0.9f; - } - - if (wpd->shading.type == OB_WIRE) { - wpd->shading.xray_alpha = 0.0f; - wpd->shading.xray_alpha_wire = 0.0f; - } - - int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS; - psl->checker_depth_pass = DRW_pass_create("Checker Depth", state); - grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass); - DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL); - DRW_shgroup_uniform_float_copy(grp, "threshold", blend_threshold); - DRW_shgroup_uniform_float_copy(grp, "offset", noise_offset); + if (wpd->shading.type == OB_WIRE) { + wpd->shading.xray_alpha = 0.0f; + wpd->shading.xray_alpha_wire = 0.0f; } } @@ -481,7 +452,6 @@ void workbench_forward_engine_free() for (int index = 0; index < 2; index++) { DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]); } - DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh); workbench_volume_engine_free(); workbench_fxaa_engine_free(); @@ -828,10 +798,6 @@ void workbench_forward_draw_scene(WORKBENCH_Data *vedata) /* Color correct and Anti aliasing */ workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx); - - /* Apply checker pattern */ - GPU_framebuffer_bind(dfbl->depth_only_fb); - DRW_draw_pass(psl->checker_depth_pass); } void workbench_forward_draw_finish(WORKBENCH_Data *vedata) diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 85e7147df1e..faf85e4a7de 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -164,7 +164,6 @@ typedef struct WORKBENCH_PassList { struct DRWPass *transparent_accum_pass; struct DRWPass *object_outline_pass; struct DRWPass *depth_pass; - struct DRWPass *checker_depth_pass; } WORKBENCH_PassList; typedef struct WORKBENCH_Data { diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 60c6e66bfe9..4f7554006cb 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -25,6 +25,8 @@ #ifndef __DRW_RENDER_H__ #define __DRW_RENDER_H__ +#include "DRW_engine_types.h" + #include "BLI_listbase.h" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" @@ -61,8 +63,6 @@ #include "DEG_depsgraph.h" -struct DefaultFramebufferList; -struct DefaultTextureList; struct GPUBatch; struct GPUFrameBuffer; struct GPUMaterial; @@ -133,25 +133,6 @@ typedef struct DrawEngineType { const struct rcti *rect); } DrawEngineType; -#ifndef __DRW_ENGINE_H__ -/* Buffer and textures used by the viewport by default */ -typedef struct DefaultFramebufferList { - struct GPUFrameBuffer *default_fb; - struct GPUFrameBuffer *overlay_fb; - struct GPUFrameBuffer *in_front_fb; - struct GPUFrameBuffer *color_only_fb; - struct GPUFrameBuffer *depth_only_fb; - struct GPUFrameBuffer *overlay_only_fb; -} DefaultFramebufferList; - -typedef struct DefaultTextureList { - struct GPUTexture *color; - struct GPUTexture *color_overlay; - struct GPUTexture *depth; - struct GPUTexture *depth_in_front; -} DefaultTextureList; -#endif - /* Textures */ typedef enum { DRW_TEX_FILTER = (1 << 0), diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 8d3c932cbe6..4f1cab40463 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -416,41 +416,44 @@ void debug_markers_print_list(ListBase *markers) /* ************* Marker Drawing ************ */ -static void marker_color_get(TimeMarker *marker, unsigned char *color) +static void marker_color_get(const TimeMarker *marker, uchar *r_text_color, uchar *r_line_color) { if (marker->flag & SELECT) { - UI_GetThemeColor4ubv(TH_TEXT_HI, color); + UI_GetThemeColor4ubv(TH_TEXT_HI, r_text_color); + UI_GetThemeColor4ubv(TH_TIME_MARKER_LINE_SELECTED, r_line_color); } else { - UI_GetThemeColor4ubv(TH_TEXT, color); + UI_GetThemeColor4ubv(TH_TEXT, r_text_color); + UI_GetThemeColor4ubv(TH_TIME_MARKER_LINE, r_line_color); } } -static void draw_marker_name(const uiFontStyle *fstyle, +static void draw_marker_name(const uchar *text_color, + const uiFontStyle *fstyle, TimeMarker *marker, float marker_x, float text_y) { - unsigned char text_color[4]; - marker_color_get(marker, text_color); - const char *name = marker->name; + uchar final_text_color[4]; + + copy_v4_v4_uchar(final_text_color, text_color); #ifdef DURIAN_CAMERA_SWITCH if (marker->camera) { Object *camera = marker->camera; name = camera->id.name + 2; if (camera->restrictflag & OB_RESTRICT_RENDER) { - text_color[3] = 100; + final_text_color[3] = 100; } } #endif int name_x = marker_x + UI_DPI_ICON_SIZE * 0.6; - UI_fontstyle_draw_simple(fstyle, name_x, text_y, name, text_color); + UI_fontstyle_draw_simple(fstyle, name_x, text_y, name, final_text_color); } -static void draw_marker_line(const float color[4], int xpos, int ymin, int ymax) +static void draw_marker_line(const uchar *color, int xpos, int ymin, int ymax) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -461,7 +464,7 @@ static void draw_marker_line(const float color[4], int xpos, int ymin, int ymax) GPU_viewport_size_get_f(viewport_size); immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC); - immUniformColor4fv(color); + immUniformColor4ubv(color); immUniform1i("colors_len", 0); /* "simple" mode */ immUniform1f("dash_width", 6.0f); immUniform1f("dash_factor", 0.5f); @@ -493,19 +496,15 @@ static int marker_get_icon_id(TimeMarker *marker, int flag) static void draw_marker( const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int xpos, int flag, int region_height) { + uchar line_color[4], text_color[4]; + + marker_color_get(marker, text_color, line_color); + GPU_blend(true); GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - float color[4]; - if (marker->flag & SELECT) { - copy_v4_fl4(color, 1.0f, 1.0f, 1.0f, 0.38f); - } - else { - copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 0.38f); - } - - draw_marker_line(color, xpos, UI_DPI_FAC * 20, region_height); + draw_marker_line(line_color, xpos, UI_DPI_FAC * 20, region_height); int icon_id = marker_get_icon_id(marker, flag); UI_icon_draw(xpos - 0.55f * UI_DPI_ICON_SIZE, UI_DPI_FAC * 18, icon_id); @@ -518,7 +517,7 @@ static void draw_marker( if ((marker->flag & SELECT) || (cfra - 4 <= marker->frame && marker->frame <= cfra)) { name_y += UI_DPI_FAC * 10; } - draw_marker_name(fstyle, marker, xpos, name_y); + draw_marker_name(text_color, fstyle, marker, xpos, name_y); } static void draw_markers_background(rctf *rect) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index a3b7d6bd1c1..cad8b34557f 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -362,13 +362,13 @@ int ED_object_modifier_convert(struct ReportList *reports, struct ViewLayer *view_layer, struct Object *ob, struct ModifierData *md); -int ED_object_modifier_apply(struct Main *bmain, - struct ReportList *reports, - struct Depsgraph *depsgraph, - struct Scene *scene, - struct Object *ob, - struct ModifierData *md, - int mode); +bool ED_object_modifier_apply(struct Main *bmain, + struct ReportList *reports, + struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob, + struct ModifierData *md, + int mode); int ED_object_modifier_copy(struct ReportList *reports, struct Object *ob, struct ModifierData *md); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 1390567d5af..d003dac7fbf 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -230,8 +230,8 @@ bool ED_screen_change(struct bContext *C, struct bScreen *sc); void ED_screen_scene_change(struct bContext *C, struct wmWindow *win, struct Scene *scene); void ED_screen_set_active_region(struct bContext *C, struct wmWindow *win, const int xy[2]); void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen); -void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable); -void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh); +void ED_screen_animation_timer(struct bContext *C, int redraws, int sync, int enable); +void ED_screen_animation_timer_update(struct bScreen *screen, int redraws); void ED_screen_restore_temp_type(struct bContext *C, ScrArea *sa); ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type); void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa); diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index c515d501a8d..bbbcaab165a 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -30,7 +30,6 @@ typedef struct ScreenAnimData { ARegion *ar; /* do not read from this, only for comparing if region exists */ short redraws; - short refresh; short flag; /* flags for playback */ int sfra; /* frame that playback was started from */ int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */ diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index fabf6baed23..6739f7cb12c 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -793,7 +793,7 @@ DEF_ICON(BOOKMARKS) DEF_ICON(FONTPREVIEW) DEF_ICON(FILTER) DEF_ICON(NEWFOLDER) -DEF_ICON(FOLDER_REDIRECT) +DEF_ICON_FOLDER(FOLDER_REDIRECT) DEF_ICON(FILE_PARENT) DEF_ICON(FILE_REFRESH) DEF_ICON_FOLDER(FILE_FOLDER) diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index e4b11977214..10ca89c8222 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -108,6 +108,8 @@ typedef enum ThemeColorID { TH_FACEDOT_SIZE, TH_CFRAME, TH_TIME_SCRUB_BACKGROUND, + TH_TIME_MARKER_LINE, + TH_TIME_MARKER_LINE_SELECTED, TH_TIME_KEYFRAME, TH_TIME_GP_KEYFRAME, TH_NURB_ULINE, diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 5710be04477..093f063ebea 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -735,6 +735,8 @@ bool UI_context_copy_to_selected_list(bContext *C, { *r_use_path_from_id = false; *r_path = NULL; + /* special case for bone constraints */ + char *path_from_bone = NULL; /* PropertyGroup objects don't have a reference to the struct that actually owns * them, so it is normally necessary to do a brute force search to find it. This @@ -797,6 +799,12 @@ bool UI_context_copy_to_selected_list(bContext *C, else if (RNA_struct_is_a(ptr->type, &RNA_FCurve)) { *r_lb = CTX_data_collection_get(C, "selected_editable_fcurves"); } + else if (RNA_struct_is_a(ptr->type, &RNA_Constraint) && + (path_from_bone = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_PoseBone)) != + NULL) { + *r_lb = CTX_data_collection_get(C, "selected_pose_bones"); + *r_path = path_from_bone; + } else if (RNA_struct_is_a(ptr->type, &RNA_Node) || RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) { ListBase lb = {NULL, NULL}; char *path = NULL; diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 867ac652505..b509f5e352b 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -555,9 +555,7 @@ static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle) /* reset to region cursor (only if there's not another menu open) */ if (BLI_listbase_is_empty(&sc->regionbase)) { - ED_region_cursor_set(win, ctx_sa, ctx_ar); - /* in case cursor needs to be changed again */ - WM_event_add_mousemove(C); + win->tag_cursor_refresh = true; } if (handle->scrolltimer) { diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 4a6ce59de9b..cdbd049346e 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -311,6 +311,12 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid) case TH_TIME_SCRUB_BACKGROUND: cp = ts->time_scrub_background; break; + case TH_TIME_MARKER_LINE: + cp = ts->time_marker_line; + break; + case TH_TIME_MARKER_LINE_SELECTED: + cp = ts->time_marker_line_selected; + break; case TH_VIEW_OVERLAY: cp = ts->view_overlay; break; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 8981221cb9c..454d3c07fff 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -1240,8 +1240,9 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) /* despite 3 layers of checks, we may still not be able to find a constraint */ if (data == NULL) { - printf("DEBUG: Child-Of Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>"); - BKE_report(op->reports, RPT_ERROR, "Could not find constraint data for Child-Of Set Inverse"); + printf("DEBUG: ObjectSolver Set Inverse - object = '%s'\n", (ob) ? ob->id.name + 2 : "<None>"); + BKE_report( + op->reports, RPT_ERROR, "Could not find constraint data for ObjectSolver Set Inverse"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index e440062738c..bac40b35102 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -754,30 +754,30 @@ static int modifier_apply_obdata( return 1; } -int ED_object_modifier_apply(Main *bmain, - ReportList *reports, - Depsgraph *depsgraph, - Scene *scene, - Object *ob, - ModifierData *md, - int mode) +bool ED_object_modifier_apply(Main *bmain, + ReportList *reports, + Depsgraph *depsgraph, + Scene *scene, + Object *ob, + ModifierData *md, + int mode) { int prev_mode; if (BKE_object_is_in_editmode(ob)) { BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in edit mode"); - return 0; + return false; } - else if (((ID *)ob->data)->us > 1) { + else if (ID_REAL_USERS(ob->data) > 1) { BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied to multi-user data"); - return 0; + return false; } else if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) && (modifier_isSameTopology(md) == false)) { BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); - return 0; + return false; } if (md != ob->modifiers.first) { @@ -796,13 +796,13 @@ int ED_object_modifier_apply(Main *bmain, if (mode == MODIFIER_APPLY_SHAPE) { if (!modifier_apply_shape(bmain, reports, depsgraph, scene, ob, md_eval)) { md_eval->mode = prev_mode; - return 0; + return false; } } else { if (!modifier_apply_obdata(reports, depsgraph, scene, ob, md_eval)) { md_eval->mode = prev_mode; - return 0; + return false; } } @@ -812,7 +812,7 @@ int ED_object_modifier_apply(Main *bmain, BKE_object_free_derived_caches(ob); - return 1; + return true; } int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierData *md) @@ -931,28 +931,28 @@ bool edit_modifier_poll_generic(bContext *C, ModifierData *mod = ptr.data; /* May be NULL. */ if (!ob || ID_IS_LINKED(ob)) { - return 0; + return false; } if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) { - return 0; + return false; } if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) { - return 0; + return false; } if (ID_IS_OVERRIDE_LIBRARY(ob)) { if ((mod != NULL) && (mod->flag & eModifierFlag_OverrideLibrary_Local) == 0) { CTX_wm_operator_poll_msg_set(C, "Cannot edit modifiers coming from library override"); - return 0; + return false; } } if (!is_editmode_allowed && CTX_data_edit_object(C) != NULL) { CTX_wm_operator_poll_msg_set(C, "This modifier operation is not allowed from Edit mode"); - return 0; + return false; } - return 1; + return true; } bool edit_modifier_poll(bContext *C) @@ -1139,6 +1139,32 @@ void OBJECT_OT_modifier_move_down(wmOperatorType *ot) /************************ apply modifier operator *********************/ +static bool modifier_apply_poll(bContext *C) +{ + if (!edit_modifier_poll_generic(C, &RNA_Modifier, 0, false)) { + return false; + } + + Scene *scene = CTX_data_scene(C); + PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", &RNA_Modifier); + Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C); + ModifierData *md = ptr.data; /* May be NULL. */ + + if (ID_REAL_USERS(ob->data) > 1) { + CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied to multi-user data"); + return false; + } + else if (md != NULL) { + if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) && + (modifier_isSameTopology(md) == false)) { + CTX_wm_operator_poll_msg_set( + C, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); + return false; + } + } + return true; +} + static int modifier_apply_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1187,7 +1213,7 @@ void OBJECT_OT_modifier_apply(wmOperatorType *ot) ot->invoke = modifier_apply_invoke; ot->exec = modifier_apply_exec; - ot->poll = edit_modifier_poll; + ot->poll = modifier_apply_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index 95bc90c8e5f..8ecaeefbd5f 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -217,13 +217,38 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) View3D *v3d = CTX_wm_view3d(C); bool changed_multi = false; + Object *obact = CTX_data_active_object(C); + const Material *mat_active = obact ? BKE_object_material_get(obact, obact->actcol) : NULL; + uint objects_len = 0; Object **objects = object_array_for_shading(C, &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *ob = objects[ob_index]; - if (ob->actcol <= 0) { + short mat_nr_active = -1; + + if (ob->totcol == 0) { continue; } + if (obact && (mat_active == BKE_object_material_get(ob, obact->actcol))) { + /* Avoid searching since there may be multiple slots with the same material. + * For the active object or duplicates: match the material slot index first. */ + mat_nr_active = obact->actcol - 1; + } + else { + /* Find the first matching material. + * Note: there may be multiple but that's not a common use case. */ + for (short i = 0; i < ob->totcol; i++) { + const Material *mat = BKE_object_material_get(ob, i + 1); + if (mat_active == mat) { + mat_nr_active = i; + break; + } + } + if (mat_nr_active == -1) { + continue; + } + } + bool changed = false; if (ob->type == OB_MESH) { BMEditMesh *em = BKE_editmesh_from_object(ob); @@ -234,7 +259,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { changed = true; - efa->mat_nr = ob->actcol - 1; + efa->mat_nr = mat_nr_active; } } } @@ -247,7 +272,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) for (nu = nurbs->first; nu; nu = nu->next) { if (ED_curve_nurb_select_check(v3d, nu)) { changed = true; - nu->mat_nr = ob->actcol - 1; + nu->mat_nr = mat_nr_active; } } } @@ -259,7 +284,7 @@ static int material_slot_assign_exec(bContext *C, wmOperator *UNUSED(op)) if (ef && BKE_vfont_select_get(ob, &selstart, &selend)) { for (i = selstart; i <= selend; i++) { changed = true; - ef->textbufinfo[i].mat_nr = ob->actcol; + ef->textbufinfo[i].mat_nr = mat_nr_active + 1; } } } diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index c9e6cd24ac0..26240482e6d 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1869,15 +1869,21 @@ void ED_region_floating_initialize(ARegion *ar) void ED_region_cursor_set(wmWindow *win, ScrArea *sa, ARegion *ar) { - if (ar && sa && ar->type && ar->type->cursor) { - ar->type->cursor(win, sa, ar); - } - else { - if (WM_cursor_set_from_tool(win, sa, ar)) { + if (ar != NULL) { + if ((ar->gizmo_map != NULL) && WM_gizmomap_cursor_set(ar->gizmo_map, win)) { + return; + } + if (sa && ar->type && ar->type->cursor) { + ar->type->cursor(win, sa, ar); return; } - WM_cursor_set(win, WM_CURSOR_DEFAULT); } + + if (WM_cursor_set_from_tool(win, sa, ar)) { + return; + } + + WM_cursor_set(win, WM_CURSOR_DEFAULT); } /* for use after changing visibility of regions */ diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 1520566cd9d..1fd3f258e6c 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -398,6 +398,15 @@ int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2) /* ****************** EXPORTED API TO OTHER MODULES *************************** */ /* screen sets cursor based on active region */ +static void region_cursor_set_ex(wmWindow *win, ScrArea *sa, ARegion *ar, bool swin_changed) +{ + BLI_assert(WM_window_get_active_screen(win)->active_region == ar); + if (win->tag_cursor_refresh || swin_changed || (ar->type && ar->type->event_cursor)) { + win->tag_cursor_refresh = false; + ED_region_cursor_set(win, sa, ar); + } +} + static void region_cursor_set(wmWindow *win, bool swin_changed) { bScreen *screen = WM_window_get_active_screen(win); @@ -406,14 +415,7 @@ static void region_cursor_set(wmWindow *win, bool swin_changed) { for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) { if (ar == screen->active_region) { - if (swin_changed || (ar->type && ar->type->event_cursor)) { - if (ar->gizmo_map != NULL) { - if (WM_gizmomap_cursor_set(ar->gizmo_map, win)) { - return; - } - } - ED_region_cursor_set(win, sa, ar); - } + region_cursor_set_ex(win, sa, ar, swin_changed); return; } } @@ -672,97 +674,98 @@ static void screen_cursor_set(wmWindow *win, const int xy[2]) } } -/* called in wm_event_system.c. sets state vars in screen, cursors */ -/* event type is mouse move */ +/** + * Called in wm_event_system.c. sets state vars in screen, cursors. + * event type is mouse move. + */ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) { bScreen *scr = WM_window_get_active_screen(win); + if (scr == NULL) { + return; + } - if (scr) { - ScrArea *sa = NULL; - ARegion *ar; - ARegion *old_ar = scr->active_region; + ScrArea *sa = NULL; + ARegion *ar; + ARegion *old_ar = scr->active_region; - ED_screen_areas_iter(win, scr, area_iter) - { - if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) { - if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) { - if (ED_area_azones_update(area_iter, xy) == NULL) { - sa = area_iter; - break; - } - } - } - } - if (sa) { - /* make overlap active when mouse over */ - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ED_region_contains_xy(ar, xy)) { - scr->active_region = ar; + ED_screen_areas_iter(win, scr, area_iter) + { + if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) { + if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) { + if (ED_area_azones_update(area_iter, xy) == NULL) { + sa = area_iter; break; } } } - else { - scr->active_region = NULL; + } + if (sa) { + /* Make overlap active when mouse over. */ + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ED_region_contains_xy(ar, xy)) { + scr->active_region = ar; + break; + } } + } + else { + scr->active_region = NULL; + } - /* check for redraw headers */ - if (old_ar != scr->active_region) { + /* Check for redraw headers. */ + if (old_ar != scr->active_region) { - ED_screen_areas_iter(win, scr, area_iter) - { - bool do_draw = false; + ED_screen_areas_iter(win, scr, area_iter) + { + bool do_draw = false; - for (ar = area_iter->regionbase.first; ar; ar = ar->next) { + for (ar = area_iter->regionbase.first; ar; ar = ar->next) { - /* call old area's deactivate if assigned */ - if (ar == old_ar && area_iter->type->deactivate) { - area_iter->type->deactivate(area_iter); - } + /* Call old area's deactivate if assigned. */ + if (ar == old_ar && area_iter->type->deactivate) { + area_iter->type->deactivate(area_iter); + } - if (ar == old_ar && ar != scr->active_region) { - wmGizmoMap *gzmap = old_ar->gizmo_map; - if (gzmap) { - if (WM_gizmo_highlight_set(gzmap, NULL)) { - ED_region_tag_redraw_no_rebuild(old_ar); - } + if (ar == old_ar && ar != scr->active_region) { + wmGizmoMap *gzmap = old_ar->gizmo_map; + if (gzmap) { + if (WM_gizmo_highlight_set(gzmap, NULL)) { + ED_region_tag_redraw_no_rebuild(old_ar); } } + } - if (ar == old_ar || ar == scr->active_region) { - do_draw = true; - } + if (ar == old_ar || ar == scr->active_region) { + do_draw = true; } + } - if (do_draw) { - for (ar = area_iter->regionbase.first; ar; ar = ar->next) { - if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { - ED_region_tag_redraw_no_rebuild(ar); - } + if (do_draw) { + for (ar = area_iter->regionbase.first; ar; ar = ar->next) { + if (ELEM(ar->regiontype, RGN_TYPE_HEADER, RGN_TYPE_TOOL_HEADER)) { + ED_region_tag_redraw_no_rebuild(ar); } } } } + } - /* cursors, for time being set always on edges, otherwise aregion doesn't switch */ - if (scr->active_region == NULL) { - screen_cursor_set(win, xy); - } - else { - /* notifier invokes freeing the buttons... causing a bit too much redraws */ - if (old_ar != scr->active_region) { - region_cursor_set(win, true); + /* Cursors, for time being set always on edges, + * otherwise the active region doesn't switch. */ + if (scr->active_region == NULL) { + screen_cursor_set(win, xy); + } + else { + /* Notifier invokes freeing the buttons... causing a bit too much redraws. */ + region_cursor_set_ex(win, sa, scr->active_region, old_ar != scr->active_region); - /* this used to be a notifier, but needs to be done immediate - * because it can undo setting the right button as active due - * to delayed notifier handling */ - if (C) { - UI_screen_free_active_but(C, scr); - } - } - else { - region_cursor_set(win, false); + if (old_ar != scr->active_region) { + /* This used to be a notifier, but needs to be done immediate + * because it can undo setting the right button as active due + * to delayed notifier handling. */ + if (C) { + UI_screen_free_active_but(C, scr); } } } @@ -1441,7 +1444,7 @@ void ED_refresh_viewport_fps(bContext *C) /* redraws: uses defines from stime->redraws * enable: 1 - forward on, -1 - backwards on, 0 - off */ -void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, int enable) +void ED_screen_animation_timer(bContext *C, int redraws, int sync, int enable) { bScreen *screen = CTX_wm_screen(C); wmWindowManager *wm = CTX_wm_manager(C); @@ -1481,7 +1484,6 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync, } } sad->redraws = redraws; - sad->refresh = refresh; sad->flag |= (enable < 0) ? ANIMPLAY_FLAG_REVERSE : 0; sad->flag |= (sync == 0) ? ANIMPLAY_FLAG_NO_SYNC : (sync == 1) ? ANIMPLAY_FLAG_SYNC : 0; @@ -1526,14 +1528,13 @@ static ARegion *time_top_left_3dwindow(bScreen *screen) return aret; } -void ED_screen_animation_timer_update(bScreen *screen, int redraws, int refresh) +void ED_screen_animation_timer_update(bScreen *screen, int redraws) { if (screen && screen->animtimer) { wmTimer *wt = screen->animtimer; ScreenAnimData *sad = wt->customdata; sad->redraws = redraws; - sad->refresh = refresh; sad->ar = NULL; if (redraws & TIME_REGION) { sad->ar = time_top_left_3dwindow(screen); diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index bd7475dc1a2..35d84d5d75e 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -4616,20 +4616,18 @@ int ED_screen_animation_play(bContext *C, int sync, int mode) if (ED_screen_animation_playing(CTX_wm_manager(C))) { /* stop playback now */ - ED_screen_animation_timer(C, 0, 0, 0, 0); + ED_screen_animation_timer(C, 0, 0, 0); BKE_sound_stop_scene(scene_eval); WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene); } else { /* these settings are currently only available from a menu in the TimeLine */ - int refresh = SPACE_ACTION; - if (mode == 1) { /* XXX only play audio forwards!? */ BKE_sound_play_scene(scene_eval); } - ED_screen_animation_timer(C, screen->redraws_flag, refresh, sync, mode); + ED_screen_animation_timer(C, screen->redraws_flag, sync, mode); if (screen->animtimer) { wmTimer *wt = screen->animtimer; diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 0aec6d5e6a0..1739c15cbc6 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -133,8 +133,15 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh true, (float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f, color); } -static void file_draw_icon( - uiBlock *block, const char *path, int sx, int sy, int icon, int width, int height, bool drag) +static void file_draw_icon(uiBlock *block, + const char *path, + int sx, + int sy, + int icon, + int width, + int height, + bool drag, + bool dimmed) { uiBut *but; int x, y; @@ -142,8 +149,11 @@ static void file_draw_icon( x = sx; y = sy - height; + /* For uiDefIconBut(), if a1==1.0 then a2 is alpha 0.0 - 1.0 */ + const float a1 = dimmed ? 1.0f : 0.0f; + const float a2 = dimmed ? 0.3f : 0.0f; but = uiDefIconBut( - block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, 0.0f, 0.0f, NULL); + block, UI_BTYPE_LABEL, 0, icon, x, y, width, height, NULL, 0.0f, 0.0f, a1, a2, NULL); UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path)); if (drag) { @@ -210,7 +220,8 @@ static void file_draw_preview(uiBlock *block, FileLayout *layout, const bool is_icon, const int typeflags, - const bool drag) + const bool drag, + const bool dimmed) { uiBut *but; float fx, fy; @@ -273,6 +284,10 @@ static void file_draw_preview(uiBlock *block, UI_GetThemeColor4fv(TH_TEXT, col); } + if (dimmed) { + col[3] *= 0.3f; + } + if (!is_icon && typeflags & FILE_TYPE_BLENDERLIB) { /* Datablock preview images use premultiplied alpha. */ GPU_blend_set_func_separate( @@ -775,6 +790,7 @@ void file_draw_list(const bContext *C, ARegion *ar) /* don't drag parent or refresh items */ do_drag = !(FILENAME_IS_CURRPAR(file->relpath)); + const bool is_hidden = (file->attributes & FILE_ATTR_HIDDEN); if (FILE_IMGDISPLAY == params->display) { const int icon = filelist_geticon(files, i, false); @@ -795,7 +811,8 @@ void file_draw_list(const bContext *C, ARegion *ar) layout, is_icon, file->typeflag, - do_drag); + do_drag, + is_hidden); } else { file_draw_icon(block, @@ -805,7 +822,8 @@ void file_draw_list(const bContext *C, ARegion *ar) filelist_geticon(files, i, true), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, - do_drag); + do_drag, + is_hidden); icon_ofs += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index b328b32263c..28e6d95beb3 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -213,6 +213,9 @@ typedef struct FileListInternEntry { /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ char *name; + /** Defined in BLI_fileops.h */ + eFileAttributes attributes; + BLI_stat_t st; } FileListInternEntry; @@ -609,54 +612,76 @@ void filelist_setsorting(struct FileList *filelist, const short sort, bool inver /* ********** Filter helpers ********** */ -static bool is_hidden_file(const char *filename, FileListFilter *filter) +/* True if filename is meant to be hidden, eg. starting with period. */ +static bool is_hidden_dot_filename(const char *filename, FileListInternEntry *file) { - char *sep = (char *)BLI_last_slash(filename); - bool is_hidden = false; - - if (filter->flags & FLF_HIDE_DOT) { - if (filename[0] == '.' && filename[1] != '.' && filename[1] != '\0') { - is_hidden = true; /* ignore .file */ - } - else { - int len = strlen(filename); - if ((len > 0) && (filename[len - 1] == '~')) { - is_hidden = true; /* ignore file~ */ - } - } + if (filename[0] == '.' && !ELEM(filename[1], '.', '\0')) { + return true; /* ignore .file */ } - if (!is_hidden && (filter->flags & FLF_HIDE_PARENT)) { - if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') { - is_hidden = true; /* ignore .. */ + else { + int len = strlen(filename); + if ((len > 0) && (filename[len - 1] == '~')) { + return true; /* ignore file~ */ } } - if (!is_hidden && ((filename[0] == '.') && (filename[1] == '\0'))) { - is_hidden = true; /* ignore . */ - } + /* filename might actually be a piece of path, in which case we have to check all its parts. */ - if (!is_hidden && sep) { + + bool hidden = false; + char *sep = (char *)BLI_last_slash(filename); + + if (!hidden && sep) { char tmp_filename[FILE_MAX_LIBEXTRA]; BLI_strncpy(tmp_filename, filename, sizeof(tmp_filename)); sep = tmp_filename + (sep - filename); while (sep) { BLI_assert(sep[1] != '\0'); - if (is_hidden_file(sep + 1, filter)) { - is_hidden = true; + if (is_hidden_dot_filename(sep + 1, file)) { + hidden = true; break; } *sep = '\0'; sep = (char *)BLI_last_slash(tmp_filename); } } - return is_hidden; + return hidden; +} + +/* True if should be hidden, based on current filtering. */ +static bool is_filtered_hidden(const char *filename, + FileListFilter *filter, + FileListInternEntry *file) +{ + if ((filename[0] == '.') && (filename[1] == '\0')) { + return true; /* Ignore . */ + } + + if (filter->flags & FLF_HIDE_PARENT) { + if (filename[0] == '.' && filename[1] == '.' && filename[2] == '\0') { + return true; /* Ignore .. */ + } + } + + if ((filter->flags & FLF_HIDE_DOT) && (file->attributes & FILE_ATTR_HIDDEN)) { + return true; /* Ignore files with Hidden attribute. */ + } + +#ifndef WIN32 + /* Check for unix-style names starting with period. */ + if ((filter->flags & FLF_HIDE_DOT) && is_hidden_dot_filename(filename, file)) { + return true; + } +#endif + + return false; } static bool is_filtered_file(FileListInternEntry *file, const char *UNUSED(root), FileListFilter *filter) { - bool is_filtered = !is_hidden_file(file->relpath, filter); + bool is_filtered = !is_filtered_hidden(file->relpath, filter, file); if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { /* We only check for types if some type are enabled in filtering. */ @@ -699,7 +724,7 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis BLI_join_dirfile(path, sizeof(path), root, file->relpath); if (BLO_library_path_explode(path, dir, &group, &name)) { - is_filtered = !is_hidden_file(file->relpath, filter); + is_filtered = !is_filtered_hidden(file->relpath, filter, file); if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) { /* We only check for types if some type are enabled in filtering. */ if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) { @@ -747,7 +772,7 @@ static bool is_filtered_main(FileListInternEntry *file, const char *UNUSED(dir), FileListFilter *filter) { - return !is_hidden_file(file->relpath, filter); + return !is_filtered_hidden(file->relpath, filter, file); } static void filelist_filter_clear(FileList *filelist) @@ -968,7 +993,7 @@ static int filelist_geticon_ex(FileDirEntry *file, else if (is_main) { /* Do not return icon for folders if icons are not 'main' draw type * (e.g. when used over previews). */ - return ICON_FILE_FOLDER; + return (file->attributes & FILE_ATTR_ANY_LINK) ? ICON_FOLDER_REDIRECT : ICON_FILE_FOLDER; } else { /* If this path is in System list then use that icon. */ @@ -984,6 +1009,19 @@ static int filelist_geticon_ex(FileDirEntry *file, } } } + + if (file->attributes & FILE_ATTR_ANY_LINK) { + return ICON_LOOP_FORWARDS; + } + else if (file->attributes & FILE_ATTR_OFFLINE) { + return ICON_ERROR; + } + else if (file->attributes & FILE_ATTR_TEMPORARY) { + return ICON_FILE_CACHE; + } + else if (file->attributes & FILE_ATTR_SYSTEM) { + return ICON_SYSTEM; + } } if (typeflag & FILE_TYPE_BLENDER) { @@ -1621,7 +1659,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid)); ret->blentype = entry->blentype; ret->typeflag = entry->typeflag; - + ret->attributes = entry->attributes; BLI_addtail(&cache->cached_entries, ret); return ret; } @@ -2401,6 +2439,7 @@ static int filelist_readjob_list_dir(const char *root, { struct direntry *files; int nbr_files, nbr_entries = 0; + char path[FILE_MAX]; nbr_files = BLI_filelist_dir_contents(root, &files); if (files) { @@ -2416,20 +2455,17 @@ static int filelist_readjob_list_dir(const char *root, entry->relpath = MEM_dupallocN(files[i].relname); entry->st = files[i].s; + BLI_join_dirfile(path, sizeof(path), root, entry->relpath); + /* Set file type. */ if (S_ISDIR(files[i].s.st_mode)) { entry->typeflag = FILE_TYPE_DIR; } else if (do_lib && BLO_has_bfile_extension(entry->relpath)) { /* If we are considering .blend files as libs, promote them to directory status. */ - char name[FILE_MAX]; - entry->typeflag = FILE_TYPE_BLENDER; - - BLI_join_dirfile(name, sizeof(name), root, entry->relpath); - /* prevent current file being used as acceptable dir */ - if (BLI_path_cmp(main_name, name) != 0) { + if (BLI_path_cmp(main_name, path) != 0) { entry->typeflag |= FILE_TYPE_DIR; } } @@ -2441,6 +2477,16 @@ static int filelist_readjob_list_dir(const char *root, } } + /* Set file attributes. */ + entry->attributes = BLI_file_attributes(path); + +#ifndef WIN32 + /* Set linux-style dot files hidden too. */ + if (is_hidden_dot_filename(entry->relpath, entry)) { + entry->attributes |= FILE_ATTR_HIDDEN; + } +#endif + BLI_addtail(entries, entry); nbr_entries++; } diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 270fe0c59dc..f4688ce17fd 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -980,6 +980,16 @@ void uiTemplateImage(uiLayout *layout, bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name); uiLayoutSetActive(sub, !is_data); } + + if (ima && iuser) { + void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); + + if (ibuf->rect_float && (ibuf->flags & IB_halffloat) == 0) { + uiItemR(col, &imaptr, "use_half_precision", 0, NULL, ICON_NONE); + } + BKE_image_release_ibuf(ima, ibuf, lock); + } } uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 6dc4a7f950c..a3fa03b18b7 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1901,6 +1901,12 @@ void IMAGE_OT_replace(wmOperatorType *ot) /** \name Save Image As Operator * \{ */ +typedef struct ImageSaveData { + ImageUser *iuser; + Image *image; + ImageFormatData im_format; +} ImageSaveData; + static char imtype_best_depth(ImBuf *ibuf, const char imtype) { const char depth_ok = BKE_imtype_valid_depths(imtype); @@ -1980,9 +1986,6 @@ static int image_save_options_init(Main *bmain, opts->im_format.views_format = ima->views_format; } - ///* XXX - this is lame, we need to make these available too! */ - // opts->subimtype = scene->r.subimtype; - BLI_strncpy(opts->filepath, ibuf->name, sizeof(opts->filepath)); /* sanitize all settings */ @@ -2030,6 +2033,8 @@ static int image_save_options_init(Main *bmain, /* color management */ BKE_color_managed_display_settings_copy(&opts->im_format.display_settings, &scene->display_settings); + + BKE_color_managed_view_settings_free(&opts->im_format.view_settings); BKE_color_managed_view_settings_copy(&opts->im_format.view_settings, &scene->view_settings); } @@ -2038,12 +2043,14 @@ static int image_save_options_init(Main *bmain, return (ibuf != NULL); } -static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOperator *op) +static void image_save_options_from_op(Main *bmain, + ImageSaveOptions *opts, + wmOperator *op, + ImageFormatData *imf) { - if (op->customdata) { + if (imf) { BKE_color_managed_view_settings_free(&opts->im_format.view_settings); - - opts->im_format = *(ImageFormatData *)op->customdata; + opts->im_format = *imf; } if (RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -2055,20 +2062,17 @@ static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOp static void image_save_options_to_op(ImageSaveOptions *opts, wmOperator *op) { if (op->customdata) { - BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings); - - *(ImageFormatData *)op->customdata = opts->im_format; + ImageSaveData *isd = op->customdata; + BKE_color_managed_view_settings_free(&isd->im_format.view_settings); + isd->im_format = opts->im_format; } RNA_string_set(op->ptr, "filepath", opts->filepath); } -static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *opts) +static bool save_image_op( + Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts) { - Main *bmain = CTX_data_main(C); - Image *ima = image_from_context(C); - ImageUser *iuser = image_user_from_context(C); - opts->relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); opts->save_copy = (RNA_struct_find_property(op->ptr, "copy") && @@ -2085,7 +2089,7 @@ static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *o /* Remember file path for next save. */ BLI_strncpy(G.ima, opts->filepath, sizeof(G.ima)); - WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + WM_main_add_notifier(NC_IMAGE | NA_EDITED, ima); return ok; } @@ -2093,8 +2097,8 @@ static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *o static void image_save_as_free(wmOperator *op) { if (op->customdata) { - ImageFormatData *im_format = (ImageFormatData *)op->customdata; - BKE_color_managed_view_settings_free(&im_format->view_settings); + ImageSaveData *isd = op->customdata; + BKE_color_managed_view_settings_free(&isd->im_format.view_settings); MEM_freeN(op->customdata); op->customdata = NULL; @@ -2105,20 +2109,32 @@ static int image_save_as_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Image *image = image_from_context(C); - ImageUser *iuser = image_user_from_context(C); ImageSaveOptions opts; + Image *image = NULL; + ImageUser *iuser = NULL; + ImageFormatData *imf = NULL; + if (op->customdata) { + ImageSaveData *isd = op->customdata; + image = isd->image; + iuser = isd->iuser; + imf = &isd->im_format; + } + else { + image = image_from_context(C); + iuser = image_user_from_context(C); + } + BKE_image_save_options_init(&opts, bmain, scene); /* just in case to initialize values, * these should be set on invoke or by the caller. */ image_save_options_init(bmain, &opts, image, iuser, false, false); - image_save_options_from_op(bmain, &opts, op); + image_save_options_from_op(bmain, &opts, op, imf); opts.do_newpath = true; - save_image_op(C, op, &opts); + save_image_op(bmain, image, iuser, op, &opts); if (opts.save_copy == false) { BKE_image_free_packedfiles(image); @@ -2131,8 +2147,8 @@ static int image_save_as_exec(bContext *C, wmOperator *op) static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op) { - ImageFormatData *imf = op->customdata; - return WM_operator_filesel_ensure_ext_imtype(op, imf); + ImageSaveData *isd = op->customdata; + return WM_operator_filesel_ensure_ext_imtype(op, &isd->im_format); } static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -2164,8 +2180,12 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS RNA_boolean_set(op->ptr, "save_as_render", save_as_render); - op->customdata = MEM_mallocN(sizeof(opts.im_format), __func__); - memcpy(op->customdata, &opts.im_format, sizeof(opts.im_format)); + ImageSaveData *isd = MEM_callocN(sizeof(*isd), __func__); + isd->image = ima; + isd->iuser = iuser; + + memcpy(&isd->im_format, &opts.im_format, sizeof(opts.im_format)); + op->customdata = isd; /* show multiview save options only if image has multiviews */ prop = RNA_struct_find_property(op->ptr, "show_multiview"); @@ -2198,12 +2218,12 @@ static bool image_save_as_draw_check_prop(PointerRNA *ptr, static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) { uiLayout *layout = op->layout; - ImageFormatData *imf = op->customdata; + ImageSaveData *isd = op->customdata; PointerRNA imf_ptr, ptr; const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview"); /* image template */ - RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); + RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->im_format, &imf_ptr); uiTemplateImageSettings(layout, &imf_ptr, false); /* main draw call */ @@ -2343,6 +2363,7 @@ static int image_save_exec(bContext *C, wmOperator *op) ImageUser *iuser = image_user_from_context(C); Scene *scene = CTX_data_scene(C); ImageSaveOptions opts; + bool ok = false; if (BKE_image_has_packedfile(image)) { /* Save packed files to memory. */ @@ -2354,21 +2375,28 @@ static int image_save_exec(bContext *C, wmOperator *op) if (image_save_options_init(bmain, &opts, image, iuser, false, false) == 0) { return OPERATOR_CANCELLED; } - image_save_options_from_op(bmain, &opts, op); + image_save_options_from_op(bmain, &opts, op, NULL); if (BLI_exists(opts.filepath) && BLI_file_is_writable(opts.filepath)) { - if (save_image_op(C, op, &opts)) { + if (save_image_op(bmain, image, iuser, op, &opts)) { /* report since this can be called from key-shortcuts */ BKE_reportf(op->reports, RPT_INFO, "Saved Image '%s'", opts.filepath); + ok = true; } } else { BKE_reportf( op->reports, RPT_ERROR, "Cannot save image, path '%s' is not writable", opts.filepath); - return OPERATOR_CANCELLED; } - return OPERATOR_FINISHED; + BKE_color_managed_view_settings_free(&opts.im_format.view_settings); + + if (ok) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 7c64255380b..d9e1216e1bb 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -396,7 +396,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, - UI_style_get()); + UI_style_get_dpi()); if (node->flag & NODE_MUTED) { uiLayoutSetActive(layout, false); @@ -491,7 +491,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) node->butr.xmax, 0, 0, - UI_style_get()); + UI_style_get_dpi()); if (node->flag & NODE_MUTED) { uiLayoutSetActive(layout, false); @@ -523,7 +523,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) NODE_WIDTH(node) - NODE_DY, NODE_DY, 0, - UI_style_get()); + UI_style_get_dpi()); if (node->flag & NODE_MUTED) { uiLayoutSetActive(layout, false); diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 9e3c9d6725d..91694cfc1ef 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -94,10 +94,6 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() -if(WITH_MOD_FLUID) - add_definitions(-DWITH_FLUID) -endif() - blender_add_lib(bf_editor_space_view3d "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") # Needed so we can use dna_type_offsets.h for defaults initialization. diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 858096f9a6d..bc81817647e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -25,7 +25,6 @@ #include "MEM_guardedalloc.h" -#include "DNA_armature_types.h" #include "DNA_gpencil_types.h" #include "DNA_mask_types.h" #include "DNA_mesh_types.h" @@ -917,7 +916,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); - initTranslation(t); + transform_mode_init(t, NULL, TFM_TRANSLATION); initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; handled = true; @@ -935,21 +934,20 @@ int transformEvent(TransInfo *t, const wmEvent *event) resetTransRestrictions(t); /* first try edge slide */ - initEdgeSlide(t); + transform_mode_init(t, NULL, TFM_EDGE_SLIDE); /* if that fails, do vertex slide */ if (t->state == TRANS_CANCEL) { resetTransModal(t); t->state = TRANS_STARTING; - initVertSlide(t); + transform_mode_init(t, NULL, TFM_VERT_SLIDE); } /* vert slide can fail on unconnected vertices (rare but possible) */ if (t->state == TRANS_CANCEL) { resetTransModal(t); - t->mode = TFM_TRANSLATION; t->state = TRANS_STARTING; restoreTransObjects(t); resetTransRestrictions(t); - initTranslation(t); + transform_mode_init(t, NULL, TFM_TRANSLATION); } initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; @@ -982,10 +980,10 @@ int transformEvent(TransInfo *t, const wmEvent *event) resetTransRestrictions(t); if (t->mode == TFM_ROTATION) { - initTrackball(t); + transform_mode_init(t, NULL, TFM_TRACKBALL); } else { - initRotation(t); + transform_mode_init(t, NULL, TFM_ROTATION); } initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; @@ -1010,7 +1008,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); - initResize(t); + transform_mode_init(t, NULL, TFM_RESIZE); initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; handled = true; @@ -1214,7 +1212,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) } else if (t->mode == TFM_ROTATION) { restoreTransObjects(t); - initTrackball(t); + transform_mode_init(t, NULL, TFM_TRACKBALL); } } else { @@ -1256,7 +1254,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); - initTranslation(t); + transform_mode_init(t, NULL, TFM_TRANSLATION); initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; handled = true; @@ -1268,7 +1266,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); - initResize(t); + transform_mode_init(t, NULL, TFM_RESIZE); initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; handled = true; @@ -1283,10 +1281,10 @@ int transformEvent(TransInfo *t, const wmEvent *event) resetTransRestrictions(t); if (t->mode == TFM_ROTATION) { - initTrackball(t); + transform_mode_init(t, NULL, TFM_TRACKBALL); } else { - initRotation(t); + transform_mode_init(t, NULL, TFM_ROTATION); } initSnapping(t, NULL); // need to reinit after mode change t->redraw |= TREDRAW_HARD; @@ -1368,7 +1366,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) restoreTransObjects(t); resetTransModal(t); resetTransRestrictions(t); - initNormalRotation(t); + transform_mode_init(t, NULL, TFM_NORMAL_ROTATION); t->redraw = TREDRAW_HARD; handled = true; } @@ -2113,145 +2111,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate); } - switch (mode) { - case TFM_TRANSLATION: - initTranslation(t); - break; - case TFM_ROTATION: - initRotation(t); - break; - case TFM_RESIZE: - initResize(t); - break; - case TFM_SKIN_RESIZE: - initSkinResize(t); - break; - case TFM_TOSPHERE: - initToSphere(t); - break; - case TFM_SHEAR: - initShear(t); - break; - case TFM_BEND: - initBend(t); - break; - case TFM_SHRINKFATTEN: - initShrinkFatten(t); - break; - case TFM_TILT: - initTilt(t); - break; - case TFM_CURVE_SHRINKFATTEN: - initCurveShrinkFatten(t); - break; - case TFM_MASK_SHRINKFATTEN: - initMaskShrinkFatten(t); - break; - case TFM_GPENCIL_SHRINKFATTEN: - initGPShrinkFatten(t); - break; - case TFM_TRACKBALL: - initTrackball(t); - break; - case TFM_PUSHPULL: - initPushPull(t); - break; - case TFM_CREASE: - initCrease(t); - break; - case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */ - /* Note: we have to pick one, use the active object. */ - TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t); - bArmature *arm = tc->poseobj->data; - if (arm->drawtype == ARM_ENVELOPE) { - initBoneEnvelope(t); - t->mode = TFM_BONE_ENVELOPE_DIST; - } - else { - initBoneSize(t); - } - break; - } - case TFM_BONE_ENVELOPE: - initBoneEnvelope(t); - break; - case TFM_BONE_ENVELOPE_DIST: - initBoneEnvelope(t); - t->mode = TFM_BONE_ENVELOPE_DIST; - break; - case TFM_EDGE_SLIDE: - case TFM_VERT_SLIDE: { - const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false); - const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false); - const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true); - if (mode == TFM_EDGE_SLIDE) { - const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true); - initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp); - } - else { - initVertSlide_ex(t, use_even, flipped, use_clamp); - } - break; - } - case TFM_BONE_ROLL: - initBoneRoll(t); - break; - case TFM_TIME_TRANSLATE: - initTimeTranslate(t); - break; - case TFM_TIME_SLIDE: - initTimeSlide(t); - break; - case TFM_TIME_SCALE: - initTimeScale(t); - break; - case TFM_TIME_DUPLICATE: - /* same as TFM_TIME_EXTEND, but we need the mode info for later - * so that duplicate-culling will work properly - */ - if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { - initTranslation(t); - } - else { - initTimeTranslate(t); - } - t->mode = mode; - break; - case TFM_TIME_EXTEND: - /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation - * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION - * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement) - * depending on which editor this was called from - */ - if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { - initTranslation(t); - } - else { - initTimeTranslate(t); - } - break; - case TFM_BAKE_TIME: - initBakeTime(t); - break; - case TFM_MIRROR: - initMirror(t); - break; - case TFM_BWEIGHT: - initBevelWeight(t); - break; - case TFM_ALIGN: - initAlign(t); - break; - case TFM_SEQ_SLIDE: - initSeqSlide(t); - break; - case TFM_NORMAL_ROTATION: - initNormalRotation(t); - break; - case TFM_GPENCIL_OPACITY: - initGPOpacity(t); - break; - } + transform_mode_init(t, op, mode); if (t->state == TRANS_CANCEL) { postTrans(C, t); diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 5d3d1d936a2..3d9a04c060b 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -1030,7 +1030,15 @@ static void create_trans_vert_customdata_layer(BMVert *v, void trans_mesh_customdata_correction_init(TransInfo *t) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - BLI_assert(tc->custom.type.data == NULL); + if (tc->custom.type.data) { + if (tc->custom.type.free_cb == trans_mesh_customdata_free_cb) { + /* Custom data correction has initiated before. */ + continue; + } + else { + BLI_assert(false); + } + } int i; BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 00f34a20cb6..c925f5c9a8e 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1374,13 +1374,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve bGPdata *gpd = CTX_data_gpencil_data(C); PropertyRNA *prop; - if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && - RNA_property_is_set(op->ptr, prop)) { - RNA_property_float_get_array(op->ptr, prop, t->center_global); - mul_v3_v3(t->center_global, t->aspect); - t->flag |= T_OVERRIDE_CENTER; - } - if (op && (prop = RNA_struct_find_property(op->ptr, "mouse_coordinate_override")) && RNA_property_is_set(op->ptr, prop)) { RNA_property_int_get_array(op->ptr, prop, t->mval); @@ -1640,7 +1633,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve (RNA_enum_get(op->ptr, "orient_type") == RNA_enum_get(op->ptr, "orient_matrix_type")))) { RNA_property_float_get_array(op->ptr, prop, &t->orient_matrix[0][0]); copy_m3_m3(t->spacemtx, t->orient_matrix); - negate_m3(t->spacemtx); /* Some transform modes use this to operate on an axis. */ t->orient_matrix_is_set = true; t->orientation.user = V3D_ORIENT_CUSTOM_MATRIX; @@ -1780,6 +1772,13 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve setTransformViewAspect(t, t->aspect); + if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && + RNA_property_is_set(op->ptr, prop)) { + RNA_property_float_get_array(op->ptr, prop, t->center_global); + mul_v3_v3(t->center_global, t->aspect); + t->flag |= T_OVERRIDE_CENTER; + } + setTransformViewMatrices(t); initNumInput(&t->num); } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index e681b649451..cdd29ccf24f 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -24,8 +24,10 @@ #include <stdlib.h> #include "DNA_anim_types.h" +#include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_gpencil_types.h" +#include "DNA_windowmanager_types.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -35,6 +37,8 @@ #include "BKE_context.h" #include "BKE_nla.h" +#include "RNA_access.h" + #include "ED_screen.h" #include "UI_interface.h" @@ -484,7 +488,7 @@ static void constraintSizeLim(TransInfo *t, TransData *td) } /* -------------------------------------------------------------------- */ -/* Transform (Rotaion Utils) */ +/* Transform (Rotation Utils) */ /** \name Transform Rotaion Utils * \{ */ @@ -1098,3 +1102,159 @@ void doAnimEdit_SnapFrame( } } /** \} */ + +/* -------------------------------------------------------------------- */ +/* Transform Mode API */ + +/** \name Transform Frame Utils + * \{ */ + +void transform_mode_init(TransInfo *t, wmOperator *op, const int mode) +{ + t->mode = mode; + + switch (mode) { + case TFM_TRANSLATION: + initTranslation(t); + break; + case TFM_ROTATION: + initRotation(t); + break; + case TFM_RESIZE: + initResize(t); + break; + case TFM_SKIN_RESIZE: + initSkinResize(t); + break; + case TFM_TOSPHERE: + initToSphere(t); + break; + case TFM_SHEAR: + initShear(t); + break; + case TFM_BEND: + initBend(t); + break; + case TFM_SHRINKFATTEN: + initShrinkFatten(t); + break; + case TFM_TILT: + initTilt(t); + break; + case TFM_CURVE_SHRINKFATTEN: + initCurveShrinkFatten(t); + break; + case TFM_MASK_SHRINKFATTEN: + initMaskShrinkFatten(t); + break; + case TFM_GPENCIL_SHRINKFATTEN: + initGPShrinkFatten(t); + break; + case TFM_TRACKBALL: + initTrackball(t); + break; + case TFM_PUSHPULL: + initPushPull(t); + break; + case TFM_CREASE: + initCrease(t); + break; + case TFM_BONESIZE: { /* used for both B-Bone width (bonesize) as for deform-dist (envelope) */ + /* Note: we have to pick one, use the active object. */ + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_OK(t); + bArmature *arm = tc->poseobj->data; + if (arm->drawtype == ARM_ENVELOPE) { + initBoneEnvelope(t); + t->mode = TFM_BONE_ENVELOPE_DIST; + } + else { + initBoneSize(t); + } + break; + } + case TFM_BONE_ENVELOPE: + initBoneEnvelope(t); + break; + case TFM_BONE_ENVELOPE_DIST: + initBoneEnvelope(t); + t->mode = TFM_BONE_ENVELOPE_DIST; + break; + case TFM_EDGE_SLIDE: + case TFM_VERT_SLIDE: { + const bool use_even = (op ? RNA_boolean_get(op->ptr, "use_even") : false); + const bool flipped = (op ? RNA_boolean_get(op->ptr, "flipped") : false); + const bool use_clamp = (op ? RNA_boolean_get(op->ptr, "use_clamp") : true); + if (mode == TFM_EDGE_SLIDE) { + const bool use_double_side = (op ? !RNA_boolean_get(op->ptr, "single_side") : true); + initEdgeSlide_ex(t, use_double_side, use_even, flipped, use_clamp); + } + else { + initVertSlide_ex(t, use_even, flipped, use_clamp); + } + break; + } + case TFM_BONE_ROLL: + initBoneRoll(t); + break; + case TFM_TIME_TRANSLATE: + initTimeTranslate(t); + break; + case TFM_TIME_SLIDE: + initTimeSlide(t); + break; + case TFM_TIME_SCALE: + initTimeScale(t); + break; + case TFM_TIME_DUPLICATE: + /* same as TFM_TIME_EXTEND, but we need the mode info for later + * so that duplicate-culling will work properly + */ + if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { + initTranslation(t); + } + else { + initTimeTranslate(t); + } + break; + case TFM_TIME_EXTEND: + /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation + * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION + * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement) + * depending on which editor this was called from + */ + if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { + initTranslation(t); + } + else { + initTimeTranslate(t); + } + break; + case TFM_BAKE_TIME: + initBakeTime(t); + break; + case TFM_MIRROR: + initMirror(t); + break; + case TFM_BWEIGHT: + initBevelWeight(t); + break; + case TFM_ALIGN: + initAlign(t); + break; + case TFM_SEQ_SLIDE: + initSeqSlide(t); + break; + case TFM_NORMAL_ROTATION: + initNormalRotation(t); + break; + case TFM_GPENCIL_OPACITY: + initGPOpacity(t); + break; + } + + /* TODO(germano): Some of these operations change the `t->mode`. + * This can be bad for Redo. + * BLI_assert(t->mode == mode); */ +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h index bb036a69a88..a8a930cc156 100644 --- a/source/blender/editors/transform/transform_mode.h +++ b/source/blender/editors/transform/transform_mode.h @@ -30,6 +30,7 @@ struct LinkNode; struct TransInfo; struct TransDataContainer; struct TransData; +struct wmOperator; /* header of TransDataEdgeSlideVert, TransDataEdgeSlideEdge */ typedef struct TransDataGenericSlideVert { @@ -56,6 +57,7 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma short getAnimEdit_SnapMode(TransInfo *t); void doAnimEdit_SnapFrame( TransInfo *t, TransData *td, TransData2D *td2d, struct AnimData *adt, short autosnap); +void transform_mode_init(TransInfo *t, struct wmOperator *op, const int mode); /* transform_mode_align.c */ void initAlign(TransInfo *t); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 1952a2c862e..ea4f1eedd81 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -512,11 +512,11 @@ void initTransformOrientation(bContext *C, TransInfo *t) t->orientation.unset = V3D_ORIENT_VIEW; copy_m3_m4(t->orient_matrix, t->viewinv); normalize_m3(t->orient_matrix); + negate_m3(t->orient_matrix); } else { copy_m3_m3(t->orient_matrix, t->spacemtx); } - negate_m3(t->orient_matrix); } } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 1e758771f6a..49acf0ca3a4 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -53,6 +53,8 @@ #include "BKE_scene.h" #include "BKE_editmesh.h" #include "BKE_layer.h" +#include "BKE_lib_id.h" +#include "BKE_mesh.h" #include "DEG_depsgraph.h" @@ -500,11 +502,15 @@ static ParamHandle *construct_param_handle_subsurfed(const Scene *scene, smd.levels = smd_real->levels; smd.subdivType = smd_real->subdivType; - initialDerived = CDDM_from_editbmesh(em, false); - derivedMesh = subsurf_make_derived_from_derived( - initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE); + { + Mesh *me_from_em = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL, ob->data); + initialDerived = CDDM_from_mesh_ex(me_from_em, CD_REFERENCE, &CD_MASK_MESH); + derivedMesh = subsurf_make_derived_from_derived( + initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE); - initialDerived->release(initialDerived); + initialDerived->release(initialDerived); + BKE_id_free(NULL, me_from_em); + } /* get the derived data */ subsurfedVerts = derivedMesh->getVertArray(derivedMesh); diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index f89a76cf49c..cc681c02009 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -71,6 +71,7 @@ void GPU_create_gl_tex(unsigned int *bind, int recth, int textarget, bool mipmap, + bool half_float, bool use_srgb, struct Image *ima); void GPU_create_gl_tex_compressed(unsigned int *bind, diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 6afff4f68f1..62a5de7ebe6 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -328,7 +328,9 @@ static uint gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf) GLenum data_type, internal_format; if (main_ibuf->rect_float) { data_type = GL_FLOAT; - internal_format = GL_RGBA16F; + internal_format = (!(main_ibuf->flags & IB_halffloat) && (ima->flag & IMA_HIGH_BITDEPTH)) ? + GL_RGBA32F : + GL_RGBA16F; } else { data_type = GL_UNSIGNED_BYTE; @@ -472,6 +474,7 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget) { uint bindcode = 0; const bool mipmap = GPU_get_mipmap(); + const bool half_float = (ibuf->flags & IB_halffloat) != 0; #ifdef WITH_DDS if (ibuf->ftype == IMB_FTYPE_DDS) { @@ -536,6 +539,7 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget) ibuf->y, textarget, mipmap, + half_float, compress_as_srgb, ima); @@ -1043,6 +1047,7 @@ void GPU_create_gl_tex(uint *bind, int recth, int textarget, bool mipmap, + bool half_float, bool use_srgb, Image *ima) { @@ -1072,7 +1077,8 @@ void GPU_create_gl_tex(uint *bind, glGenTextures(1, (GLuint *)bind); glBindTexture(textarget, *bind); - GLenum internal_format = (frect) ? GL_RGBA16F : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8; + GLenum float_format = (!half_float && ima->flag & IMA_HIGH_BITDEPTH) ? GL_RGBA32F : GL_RGBA16F; + GLenum internal_format = (frect) ? float_format : (use_srgb) ? GL_SRGB8_ALPHA8 : GL_RGBA8; if (textarget == GL_TEXTURE_2D) { if (frect) { @@ -1236,18 +1242,21 @@ void GPU_create_gl_tex_compressed(unsigned int *bind, int textarget, Image *ima, const bool use_srgb = !(IMB_colormanagement_space_is_data(ibuf->rect_colorspace) || IMB_colormanagement_space_is_scene_linear(ibuf->rect_colorspace)); const bool mipmap = GPU_get_mipmap(); + const bool half_float = (ibuf->flags & IB_halffloat) != 0; #ifndef WITH_DDS (void)ibuf; /* Fall back to uncompressed if DDS isn't enabled */ - GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, use_srgb, ima); + GPU_create_gl_tex( + bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, half_float, use_srgb, ima); #else glGenTextures(1, (GLuint *)bind); glBindTexture(textarget, *bind); if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf, use_srgb) == 0) { glDeleteTextures(1, (GLuint *)bind); - GPU_create_gl_tex(bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, use_srgb, ima); + GPU_create_gl_tex( + bind, ibuf->rect, NULL, ibuf->x, ibuf->y, textarget, mipmap, half_float, use_srgb, ima); } glBindTexture(textarget, 0); diff --git a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl index e8323520af5..73f40c693ae 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_overlays_merge_frag.glsl @@ -33,6 +33,7 @@ void main() vec4 overlay_col = texture(overlays_texture, texCoord_interp.st); + fragColor = clamp(fragColor, 0.0, 1.0); fragColor *= 1.0 - overlay_col.a; fragColor += overlay_col; diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl index f9f195c31d6..cc12e3f78a5 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl @@ -1,9 +1,13 @@ flat in vec4 color_flat; noperspective in vec2 texCoord_interp; +flat in int glyph_offset; +flat in ivec2 glyph_dim; +flat in int interp_size; + out vec4 fragColor; -uniform sampler2D glyph; +uniform sampler1DArray glyph; const vec2 offsets4[4] = vec2[4]( vec2(-0.5, 0.5), vec2(0.5, 0.5), vec2(-0.5, -0.5), vec2(-0.5, -0.5)); @@ -25,54 +29,108 @@ const vec2 offsets16[16] = vec2[16](vec2(-1.5, 1.5), vec2(0.5, -1.5), vec2(1.5, -1.5)); -#define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r +//#define GPU_NEAREST +#define sample_glyph_offset(texel, ofs) \ + texture_1D_custom_bilinear_filter(texCoord_interp + ofs * texel) + +float texel_fetch(int index) +{ + int size_x = textureSize(glyph, 0).r; + if (index >= size_x) { + return texelFetch(glyph, ivec2(index % size_x, index / size_x), 0).r; + } + return texelFetch(glyph, ivec2(index, 0), 0).r; +} + +bool is_inside_box(ivec2 v) +{ + return all(greaterThanEqual(v, ivec2(0))) && all(lessThan(v, glyph_dim)); +} + +float texture_1D_custom_bilinear_filter(vec2 uv) +{ + vec2 texel_2d = uv * glyph_dim + 0.5; + ivec2 texel_2d_near = ivec2(texel_2d) - 1; + int frag_offset = glyph_offset + texel_2d_near.y * glyph_dim.x + texel_2d_near.x; + + float tl = 0.0; + + if (is_inside_box(texel_2d_near)) { + tl = texel_fetch(frag_offset); + } + +#ifdef GPU_NEAREST + return tl; +#else // GPU_LINEAR + int offset_x = 1; + int offset_y = glyph_dim.x; + + float tr = 0.0; + float bl = 0.0; + float br = 0.0; + + if (is_inside_box(texel_2d_near + ivec2(1, 0))) { + tr = texel_fetch(frag_offset + offset_x); + } + if (is_inside_box(texel_2d_near + ivec2(0, 1))) { + bl = texel_fetch(frag_offset + offset_y); + } + if (is_inside_box(texel_2d_near + ivec2(1, 1))) { + br = texel_fetch(frag_offset + offset_x + offset_y); + } + + vec2 f = fract(texel_2d); + float tA = mix(tl, tr, f.x); + float tB = mix(bl, br, f.x); + + return mix(tA, tB, f.y); +#endif +} void main() { // input color replaces texture color fragColor.rgb = color_flat.rgb; - vec2 texel = 1.0 / vec2(textureSize(glyph, 0)); - vec2 texco = abs(texCoord_interp); - // modulate input alpha & texture alpha - if (texCoord_interp.x > 0) { - fragColor.a = texture(glyph, texco).r; + if (interp_size == 0) { + fragColor.a = texture_1D_custom_bilinear_filter(texCoord_interp); } else { + vec2 texel = 1.0 / glyph_dim; fragColor.a = 0.0; - if (texCoord_interp.y > 0) { + if (interp_size == 1) { /* 3x3 blur */ /* Manual unroll for perf. (stupid glsl compiler) */ - fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]); - fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]); - fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]); - fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]); + fragColor.a += sample_glyph_offset(texel, offsets4[0]); + fragColor.a += sample_glyph_offset(texel, offsets4[1]); + fragColor.a += sample_glyph_offset(texel, offsets4[2]); + fragColor.a += sample_glyph_offset(texel, offsets4[3]); fragColor.a *= (1.0 / 4.0); } else { /* 5x5 blur */ /* Manual unroll for perf. (stupid glsl compiler) */ - fragColor.a += sample_glyph_offset(texco, texel, offsets16[0]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[1]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[2]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[3]); - - fragColor.a += sample_glyph_offset(texco, texel, offsets16[4]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[5]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[6]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[7]); - - fragColor.a += sample_glyph_offset(texco, texel, offsets16[8]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[9]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]); - - fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]); + fragColor.a += sample_glyph_offset(texel, offsets16[0]); + fragColor.a += sample_glyph_offset(texel, offsets16[1]); + fragColor.a += sample_glyph_offset(texel, offsets16[2]); + fragColor.a += sample_glyph_offset(texel, offsets16[3]); + + fragColor.a += sample_glyph_offset(texel, offsets16[4]); + fragColor.a += sample_glyph_offset(texel, offsets16[5]) * 2.0; + fragColor.a += sample_glyph_offset(texel, offsets16[6]) * 2.0; + fragColor.a += sample_glyph_offset(texel, offsets16[7]); + + fragColor.a += sample_glyph_offset(texel, offsets16[8]); + fragColor.a += sample_glyph_offset(texel, offsets16[9]) * 2.0; + fragColor.a += sample_glyph_offset(texel, offsets16[10]) * 2.0; + fragColor.a += sample_glyph_offset(texel, offsets16[11]); + + fragColor.a += sample_glyph_offset(texel, offsets16[12]); + fragColor.a += sample_glyph_offset(texel, offsets16[13]); + fragColor.a += sample_glyph_offset(texel, offsets16[14]); + fragColor.a += sample_glyph_offset(texel, offsets16[15]); fragColor.a *= (1.0 / 20.0); } } diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl index 28437208e91..768638e5229 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl @@ -2,20 +2,33 @@ uniform mat4 ModelViewProjectionMatrix; in vec4 pos; /* rect */ -in vec4 tex; /* rect */ in vec4 col; +in int offset; +in ivec2 glyph_size; flat out vec4 color_flat; noperspective out vec2 texCoord_interp; +flat out int glyph_offset; +flat out ivec2 glyph_dim; +flat out int interp_size; void main() { + color_flat = col; + glyph_offset = offset; + glyph_dim = abs(glyph_size); + interp_size = int(glyph_size.x < 0) + int(glyph_size.y < 0); + /* Quad expension using instanced rendering. */ float x = float(gl_VertexID % 2); float y = float(gl_VertexID / 2); vec2 quad = vec2(x, y); - gl_Position = ModelViewProjectionMatrix * vec4(mix(pos.xy, pos.zw, quad), 0.0, 1.0); - texCoord_interp = mix(abs(tex.xy), abs(tex.zw), quad) * sign(tex.xw); - color_flat = col; + vec2 interp_offset = float(interp_size) / abs(pos.zw - pos.xy); + texCoord_interp = mix(-interp_offset, 1.0 + interp_offset, quad); + + vec2 final_pos = mix( + pos.xy + ivec2(-interp_size, interp_size), pos.zw + ivec2(interp_size, -interp_size), quad); + + gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 0.0, 1.0); } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl index e029905a908..714792489f6 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl @@ -4,8 +4,8 @@ void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) N = normalize(N); result = CLOSURE_DEFAULT; eevee_closure_diffuse(N, color.rgb, 1.0, true, result.radiance); + result.radiance = render_pass_diffuse_mask(color.rgb, result.radiance * color.rgb); closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); - result.radiance *= color.rgb; } #else /* Stub diffuse because it is not compatible with volumetrics. */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl index 34062cc8d02..747395857ee 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl @@ -32,7 +32,9 @@ void node_eevee_specular(vec4 diffuse, float alpha = 1.0 - transp; result = CLOSURE_DEFAULT; - result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; + result.radiance = render_pass_diffuse_mask(diffuse.rgb, out_diff * diffuse.rgb); + result.radiance += render_pass_glossy_mask(vec3(1.0), out_spec); + result.radiance += render_pass_emission_mask(emissive.rgb); result.radiance *= alpha; result.transmittance = vec3(transp); diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl index 092b9ed08bb..502bc7f92d6 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl @@ -2,7 +2,7 @@ void node_emission(vec4 color, float strength, vec3 vN, out Closure result) { result = CLOSURE_DEFAULT; #ifndef VOLUMETRICS - result.radiance = color.rgb * strength; + result.radiance = render_pass_emission_mask(color.rgb) * strength; result.ssr_normal = normal_encode(vN, viewCameraVec); #else result.emission = color.rgb * strength; diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl index 5038cb3892f..ece770f0e73 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl @@ -17,12 +17,12 @@ void node_bsdf_glass( out_spec, out_refr, ssr_spec); - out_refr *= refr_color; - out_spec *= color.rgb; float fresnel = F_eta(ior, dot(N, cameraVec)); vec3 vN = mat3(ViewMatrix) * N; result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); + result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color) * (1.0 - fresnel); + result.radiance += render_pass_glossy_mask(color.rgb, out_spec * color.rgb) * fresnel; + closure_load_ssr_data( ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result); } diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl index 75cc2e770c5..7513c3a4edb 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl @@ -7,7 +7,7 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec); vec3 vN = mat3(ViewMatrix) * N; result = CLOSURE_DEFAULT; - result.radiance = out_spec * color.rgb; + result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec) * color.rgb; closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result); } #else diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 7af409dd410..3c85dc6456c 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -18,15 +18,22 @@ void convert_metallic_to_specular_tinted(vec3 basecol, diffuse = basecol * (1.0 - metallic); } -vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint) +/* Output sheen is to be multiplied by sheen_color. */ +void principled_sheen(float NV, + vec3 basecol_tint, + float sheen, + float sheen_tint, + out float out_sheen, + out vec3 sheen_color) { float f = 1.0 - NV; /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, * therefore we need to clamp value. */ f = clamp(f, 0.0, 1.0); /* Empirical approximation (manual curve fitting). Can be refined. */ - float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; - return sheen * mix(vec3(1.0), basecol_tint, sheen_tint); + out_sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; + + sheen_color = sheen * mix(vec3(1.0), basecol_tint, sheen_tint); } void node_bsdf_principled(vec4 base_color, @@ -61,18 +68,23 @@ void node_bsdf_principled(vec4 base_color, ior = max(ior, 1e-5); metallic = saturate(metallic); transmission = saturate(transmission); + float m_transmission = 1.0 - transmission; + float dielectric = 1.0 - metallic; transmission *= dielectric; sheen *= dielectric; subsurface_color *= dielectric; - vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec; + vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec, sheen_color; + float out_sheen; vec3 ctint = tint_from_color(base_color.rgb); convert_metallic_to_specular_tinted( base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color); + + vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); /* Far from being accurate, but 2 glossy evaluation is too expensive. * Most noticeable difference is at grazing angles since the bsdf lut @@ -81,8 +93,12 @@ void node_bsdf_principled(vec4 base_color, float fresnel = F_eta(ior, NV); vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; f0 = mix(f0, spec_col, transmission); + f90 = mix(f90, spec_col, transmission); - vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); + /* Really poor approximation but needed to workaround issues with renderpasses. */ + spec_col = mix(vec3(1.0), spec_col, transmission); + /* Match cycles. */ + spec_col += float(clearcoat > 1e-5); vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); @@ -108,19 +124,22 @@ void node_bsdf_principled(vec4 base_color, vec3 refr_color = base_color.rgb; refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */ - out_refr *= refr_color * (1.0 - fresnel) * transmission; + refr_color *= saturate(1.0 - fresnel) * transmission; + + sheen_color *= m_transmission; + mixed_ss_base_color *= m_transmission; result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_refr; - result.radiance += out_diff * out_sheen; /* Coarse approx. */ - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color); + result.radiance += render_pass_glossy_mask(spec_col, out_spec); + /* Coarse approx. */ + result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - mixed_ss_base_color *= alpha * (1.0 - transmission); + mixed_ss_base_color *= alpha; closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result); - result.transmittance = vec3(1.0 - alpha); } @@ -156,22 +175,26 @@ void node_bsdf_principled_dielectric(vec4 base_color, metallic = saturate(metallic); float dielectric = 1.0 - metallic; - vec3 diffuse, f0, out_diff, out_spec, ssr_spec; + vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color; + float out_sheen; vec3 ctint = tint_from_color(base_color.rgb); convert_metallic_to_specular_tinted( base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); + float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color); eevee_closure_default( - N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec); + N, diffuse, f0, f90, int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec); result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_diff * (diffuse + out_sheen); - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); + result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color); + result.radiance += render_pass_diffuse_mask(diffuse, out_diff * diffuse); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); result.transmittance = vec3(1.0 - alpha); @@ -214,10 +237,9 @@ void node_bsdf_principled_metallic(vec4 base_color, N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec); result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); result.transmittance = vec3(1.0 - alpha); @@ -268,10 +290,12 @@ void node_bsdf_principled_clearcoat(vec4 base_color, true, out_spec, ssr_spec); + /* Match cycles. */ + float spec_col = 1.0 + float(clearcoat > 1e-5); result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(spec_col), out_spec); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); @@ -310,7 +334,8 @@ void node_bsdf_principled_subsurface(vec4 base_color, metallic = saturate(metallic); N = normalize(N); - vec3 diffuse, f0, out_diff, out_spec, ssr_spec; + vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color; + float out_sheen; vec3 ctint = tint_from_color(base_color.rgb); convert_metallic_to_specular_tinted( base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); @@ -320,7 +345,7 @@ void node_bsdf_principled_subsurface(vec4 base_color, float sss_scalef = avg(sss_scale) * subsurface; float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color); vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); @@ -338,14 +363,14 @@ void node_bsdf_principled_subsurface(vec4 base_color, ssr_spec); result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.radiance += out_diff * out_sheen; - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); + result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - mixed_ss_base_color *= alpha * (1.0 - transmission); + mixed_ss_base_color *= alpha; closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result); result.transmittance = vec3(1.0 - alpha); @@ -400,16 +425,18 @@ void node_bsdf_principled_glass(vec4 base_color, vec3 refr_color = base_color.rgb; refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission events */ - out_refr *= refr_color; float fresnel = F_eta(ior, dot(N, cameraVec)); vec3 spec_col = F_color_blend(ior, fresnel, f0); - out_spec *= spec_col; - ssr_spec *= spec_col * fresnel; + spec_col *= fresnel; + refr_color *= (1.0 - fresnel); + + ssr_spec *= spec_col; result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color); + result.radiance += render_pass_glossy_mask(spec_col, out_spec * spec_col); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); result.transmittance = vec3(1.0 - alpha); diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl index 906964e1539..4088d6db06a 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl @@ -8,7 +8,7 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl vec3 vN = mat3(ViewMatrix) * N; result = CLOSURE_DEFAULT; result.ssr_normal = normal_encode(vN, viewCameraVec); - result.radiance = out_refr * color.rgb; + result.radiance = render_pass_glossy_mask(color.rgb, out_refr * color.rgb); } #else /* Stub refraction because it is not compatible with volumetrics. */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl index 241228c0d4c..9bbbe71b206 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl @@ -19,6 +19,7 @@ void node_subsurface_scattering(vec4 color, /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */ vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur); out_diff *= mix(vec3(1.0), color.rgb, texture_blur); + result.radiance = render_pass_sss_mask(sss_albedo); closure_load_sss_data(scale, out_diff, sss_albedo, int(sss_id), result); } #else diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl index 749b3a4c11f..5c3ed81410a 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl @@ -5,7 +5,7 @@ void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) result = CLOSURE_DEFAULT; eevee_closure_diffuse(-N, color.rgb, 1.0, false, result.radiance); closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result); - result.radiance *= color.rgb; + result.radiance = render_pass_diffuse_mask(color.rgb, result.radiance * color.rgb); } #else /* Stub translucent because it is not compatible with volumetrics. */ diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl index 7d707706a03..405821e01e3 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_rotate.glsl @@ -50,33 +50,3 @@ void node_vector_rotate_euler_xyz( { vec = euler_to_mat3(rotation) * (vector_in - center) + center; } - -void node_vector_rotate_euler_xzy( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) -{ - vec = euler_to_mat3(-rotation.xzy) * (vector_in - center) + center; -} - -void node_vector_rotate_euler_yxz( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) -{ - vec = euler_to_mat3(-rotation.yxz) * (vector_in - center) + center; -} - -void node_vector_rotate_euler_yzx( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) -{ - vec = euler_to_mat3(rotation.yzx) * (vector_in - center) + center; -} - -void node_vector_rotate_euler_zxy( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) -{ - vec = euler_to_mat3(rotation.zxy) * (vector_in - center) + center; -} - -void node_vector_rotate_euler_zyx( - vec3 vector_in, vec3 center, vec3 axis, float angle, vec3 rotation, out vec3 vec) -{ - vec = euler_to_mat3(-rotation.zyx) * (vector_in - center) + center; -} diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index 61aa1f401a0..0568c425e78 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -291,6 +291,7 @@ enum { IB_alphamode_ignore = 1 << 15, IB_thumbnail = 1 << 16, IB_multiview = 1 << 17, + IB_halffloat = 1 << 18, }; /** \} */ diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index e001b8b21c4..4746cec41d4 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -194,7 +194,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac { struct ImBuf *ibuf = NULL; int width, height, components; - bool is_float, is_alpha; + bool is_float, is_alpha, is_half; int basesize; char file_colorspace[IM_MAX_SPACE]; const bool is_colorspace_manually_set = (colorspace[0] != '\0'); @@ -243,6 +243,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac is_alpha = spec.alpha_channel != -1; basesize = spec.format.basesize(); is_float = basesize > 1; + is_half = spec.format == TypeDesc::HALF; /* we only handle certain number of components */ if (!(components >= 1 && components <= 4)) { @@ -271,6 +272,7 @@ struct ImBuf *imb_load_photoshop(const char *filename, int flags, char colorspac ibuf->ftype = IMB_FTYPE_PSD; ibuf->channels = 4; ibuf->planes = (3 + (is_alpha ? 1 : 0)) * 4 << basesize; + ibuf->flags |= (is_float && is_half) ? IB_halffloat : 0; try { return ibuf; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index e1513169736..9fa2c7a28c5 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1757,6 +1757,18 @@ static bool exr_has_alpha(MultiPartInputFile &file) return !(file.header(0).channels().findChannel("A") == NULL); } +static bool exr_is_half_float(MultiPartInputFile &file) +{ + const ChannelList &channels = file.header(0).channels(); + for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) { + const Channel &channel = i.channel(); + if (channel.type != HALF) { + return false; + } + } + return true; +} + static bool imb_exr_is_multilayer_file(MultiPartInputFile &file) { const ChannelList &channels = file.header(0).channels(); @@ -1909,6 +1921,7 @@ struct ImBuf *imb_load_openexr(const unsigned char *mem, const int is_alpha = exr_has_alpha(*file); ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0); + ibuf->flags |= exr_is_half_float(*file) ? IB_halffloat : 0; if (hasXDensity(file->header(0))) { ibuf->ppm[0] = xDensity(file->header(0)) * 39.3700787f; diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 73a9e7f8a0a..03de4fb0473 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -192,7 +192,7 @@ typedef struct Image { /* Image.flag */ enum { - IMA_FLAG_UNUSED_0 = (1 << 0), /* cleared */ + IMA_HIGH_BITDEPTH = (1 << 0), IMA_FLAG_UNUSED_1 = (1 << 1), /* cleared */ #ifdef DNA_DEPRECATED_ALLOW IMA_DO_PREMUL = (1 << 2), diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 5480bed51e8..09d02e9a375 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -28,6 +28,26 @@ extern "C" { #include "DNA_freestyle_types.h" #include "DNA_listBase.h" +/* Renderpasses for EEVEE. + * ViewLayerEEVEE.render_passes */ +typedef enum eViewLayerEEVEEPassType { + EEVEE_RENDER_PASS_COMBINED = (1 << 0), + EEVEE_RENDER_PASS_Z = (1 << 1), + EEVEE_RENDER_PASS_MIST = (1 << 2), + EEVEE_RENDER_PASS_NORMAL = (1 << 3), + EEVEE_RENDER_PASS_DIFFUSE_LIGHT = (1 << 4), + EEVEE_RENDER_PASS_DIFFUSE_COLOR = (1 << 5), + EEVEE_RENDER_PASS_SPECULAR_LIGHT = (1 << 6), + EEVEE_RENDER_PASS_SPECULAR_COLOR = (1 << 7), + EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE = (1 << 8), + EEVEE_RENDER_PASS_VOLUME_SCATTER = (1 << 9), + EEVEE_RENDER_PASS_EMIT = (1 << 10), + EEVEE_RENDER_PASS_ENVIRONMENT = (1 << 11), + EEVEE_RENDER_PASS_SHADOW = (1 << 12), + EEVEE_RENDER_PASS_AO = (1 << 13), + EEVEE_RENDER_PASS_BLOOM = (1 << 14), +} eViewLayerEEVEEPassType; + typedef struct Base { struct Base *next, *prev; @@ -76,6 +96,12 @@ typedef struct LayerCollection { short _pad2[3]; } LayerCollection; +/* Type containing EEVEE settings per view-layer */ +typedef struct ViewLayerEEVEE { + int render_passes; + int _pad[1]; +} ViewLayerEEVEE; + typedef struct ViewLayer { struct ViewLayer *next, *prev; /** MAX_NAME. */ @@ -106,6 +132,7 @@ typedef struct ViewLayer { struct IDProperty *id_properties; struct FreestyleConfig freestyle_config; + struct ViewLayerEEVEE eevee; /* Runtime data */ /** ViewLayerEngineData. */ diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5f7c42b7521..44d44b92499 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1212,11 +1212,6 @@ enum { NODE_VECTOR_ROTATE_TYPE_AXIS_Y = 2, NODE_VECTOR_ROTATE_TYPE_AXIS_Z = 3, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ = 4, - NODE_VECTOR_ROTATE_TYPE_EULER_XZY = 5, - NODE_VECTOR_ROTATE_TYPE_EULER_YXZ = 6, - NODE_VECTOR_ROTATE_TYPE_EULER_YZX = 7, - NODE_VECTOR_ROTATE_TYPE_EULER_ZXY = 8, - NODE_VECTOR_ROTATE_TYPE_EULER_ZYX = 9, }; /* math node clamp */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 7cd6b5f5013..71f701b87ad 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -318,6 +318,9 @@ typedef enum eScenePassType { #define RE_PASSNAME_SUBSURFACE_COLOR "SubsurfaceCol" #define RE_PASSNAME_FREESTYLE "Freestyle" +#define RE_PASSNAME_BLOOM "BloomCol" +#define RE_PASSNAME_VOLUME_TRANSMITTANCE "VolumeTransmCol" +#define RE_PASSNAME_VOLUME_SCATTER "VolumeScatterCol" /* View - MultiView */ typedef struct SceneRenderView { @@ -1923,25 +1926,6 @@ enum { R_COLOR_MANAGEMENT_UNUSED_1 = (1 << 1), }; -#ifdef DNA_DEPRECATED_ALLOW -/* RenderData.subimtype flag options for imtype */ -enum { - R_OPENEXR_HALF = (1 << 0), /*deprecated*/ - R_OPENEXR_ZBUF = (1 << 1), /*deprecated*/ - R_PREVIEW_JPG = (1 << 2), /*deprecated*/ - R_CINEON_LOG = (1 << 3), /*deprecated*/ - R_TIFF_16BIT = (1 << 4), /*deprecated*/ - - R_JPEG2K_12BIT = (1 << 5), - /* Jpeg2000 */ /*deprecated*/ - R_JPEG2K_16BIT = (1 << 6), /*deprecated*/ - R_JPEG2K_YCC = (1 << 7), - /* when disabled use RGB */ /*deprecated*/ - R_JPEG2K_CINE_PRESET = (1 << 8), /*deprecated*/ - R_JPEG2K_CINE_48FPS = (1 << 9), /*deprecated*/ -}; -#endif - /* bake_mode: same as RE_BAKE_xxx defines */ /* RenderData.bake_flag */ #define R_BAKE_CLEAR (1 << 0) diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 483e5c4a952..8fec5354d36 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -474,8 +474,8 @@ enum { /** Update size of regions within the area. */ AREA_FLAG_REGION_SIZE_UPDATE = (1 << 3), AREA_FLAG_ACTIVE_TOOL_UPDATE = (1 << 4), + // AREA_FLAG_UNUSED_5 = (1 << 5), - // AREA_FLAG_UNUSED_5 = (1 << 5), AREA_FLAG_UNUSED_6 = (1 << 6), /* cleared */ /** diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 159c0424ee8..bdfe5040794 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -965,6 +965,8 @@ typedef struct FileDirEntry { short status; short flags; + /* eFileAttributes defined in BLI_fileops.h */ + int attributes; ListBase variants; int nbr_variants; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 8459447a688..d0d966381d1 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -289,6 +289,7 @@ typedef struct ThemeSpace { unsigned char time_keyframe[4], time_gp_keyframe[4]; unsigned char freestyle_edge_mark[4], freestyle_face_mark[4]; unsigned char time_scrub_background[4]; + unsigned char time_marker_line[4], time_marker_line_selected[4]; unsigned char nurb_uline[4], nurb_vline[4]; unsigned char act_spline[4], nurb_sel_uline[4], nurb_sel_vline[4], lastsel_point[4]; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 9a3bbee115b..c45a1480087 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -170,6 +170,7 @@ typedef struct View3DShading { float studiolight_rot_z; float studiolight_background; float studiolight_intensity; + float studiolight_blur; float object_outline_color[3]; float xray_alpha; @@ -185,7 +186,6 @@ typedef struct View3DShading { /* Render pass displayed in the viewport. Is an `eScenePassType` where one bit is set */ int render_pass; - char _pad2[4]; struct IDProperty *prop; } View3DShading; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index b1a797a35fe..491b481d001 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -239,11 +239,10 @@ typedef struct wmWindow { /** Window coords. */ short posx, posy, sizex, sizey; /** Borderless, full. */ - short windowstate; - /** Multiscreen... no idea how to store yet. */ - short monitor; + char windowstate; /** Set to 1 if an active window, for quick rejects. */ - short active; + char active; + char _pad0[4]; /** Current mouse cursor type. */ short cursor; /** Previous cursor when setting modal one. */ @@ -254,7 +253,8 @@ typedef struct wmWindow { short grabcursor; /** Internal: tag this for extra mousemove event, * makes cursors/buttons active on UI switching. */ - short addmousemove; + char addmousemove; + char tag_cursor_refresh; /** Winid also in screens, is for retrieving this window after read. */ int winid; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 7d82b97868d..41858fffcf5 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -677,6 +677,7 @@ extern StructRNA RNA_View3DCursor; extern StructRNA RNA_View3DOverlay; extern StructRNA RNA_View3DShading; extern StructRNA RNA_ViewLayer; +extern StructRNA RNA_ViewLayerEEVEE; extern StructRNA RNA_VoronoiTexture; extern StructRNA RNA_WalkNavigation; extern StructRNA RNA_WarpModifier; diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index a87a091f15e..d4bc02bbf3e 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1711,7 +1711,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Maximum Trapped Air Potential", "Upper clamping threshold for marking fluid cells where air is trapped " - "(highe value results in less marked cells)"); + "(higher value results in less marked cells)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_resetCache"); prop = RNA_def_property(srna, "sndparticle_potential_min_energy", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index 9f5f1635536..94b5786665c 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -193,6 +193,17 @@ static char *rna_ImageUser_path(PointerRNA *ptr) return BLI_strdup(""); } +static void rna_Image_gpu_texture_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + Image *ima = (Image *)ptr->owner_id; + + if (!G.background) { + GPU_free_image(ima); + } + + WM_main_add_notifier(NC_IMAGE | ND_DISPLAY, &ima->id); +} + static const EnumPropertyItem *rna_Image_source_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), @@ -1119,6 +1130,13 @@ static void rna_def_image(BlenderRNA *brna) "when saving and loading the image"); RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_colormanage_update"); + prop = RNA_def_property(srna, "use_half_precision", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMA_HIGH_BITDEPTH); + RNA_def_property_ui_text(prop, + "Half Float Precision", + "Use 16bits per channel to lower the memory usage during rendering"); + RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, "rna_Image_gpu_texture_update"); + /* multiview */ prop = RNA_def_property(srna, "views_format", PROP_ENUM, PROP_NONE); RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 5e21fc883a9..689b36ffea0 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2274,7 +2274,7 @@ static void rna_def_mesh_looptris(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - RNA_def_property_srna(cprop, "MeshLoopTriangle"); + RNA_def_property_srna(cprop, "MeshLoopTriangles"); srna = RNA_def_struct(brna, "MeshLoopTriangles", NULL); RNA_def_struct_sdna(srna, "Mesh"); RNA_def_struct_ui_text( diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 36bb65294fb..c4672ead29d 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -131,37 +131,7 @@ const EnumPropertyItem rna_enum_vector_rotate_type_items[] = { {NODE_VECTOR_ROTATE_TYPE_AXIS_X, "X_AXIS", 0, "X Axis", "Rotate a point using X axis"}, {NODE_VECTOR_ROTATE_TYPE_AXIS_Y, "Y_AXIS", 0, "Y Axis", "Rotate a point using Y axis"}, {NODE_VECTOR_ROTATE_TYPE_AXIS_Z, "Z_AXIS", 0, "Z Axis", "Rotate a point using Z axis"}, - {NODE_VECTOR_ROTATE_TYPE_EULER_XYZ, - "EULER_XYZ", - 0, - "XYZ Euler", - "Rotate a point using XYZ order"}, - - {NODE_VECTOR_ROTATE_TYPE_EULER_XZY, - "EULER_XZY", - 0, - "XZY Euler", - "Rotate a point using XZY order"}, - {NODE_VECTOR_ROTATE_TYPE_EULER_YXZ, - "EULER_YXZ", - 0, - "YXZ Euler", - "Rotate a point using YXZ order"}, - {NODE_VECTOR_ROTATE_TYPE_EULER_YZX, - "EULER_YZX", - 0, - "YZX Euler", - "Rotate a point using YZX order"}, - {NODE_VECTOR_ROTATE_TYPE_EULER_ZXY, - "EULER_ZXY", - 0, - "ZXY Euler", - "Rotate a point using ZXY order"}, - {NODE_VECTOR_ROTATE_TYPE_EULER_ZYX, - "EULER_ZYX", - 0, - "XZY Euler", - "Rotate a point using ZYX order"}, + {NODE_VECTOR_ROTATE_TYPE_EULER_XYZ, "EULER_XYZ", 0, "Euler", "Rotate a point using XYZ order"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index c0daedba95c..a3cf6fcd0b7 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -86,7 +86,6 @@ const EnumPropertyItem rna_enum_bake_pass_type_items[] = { {SCE_PASS_DIFFUSE_COLOR, "DIFFUSE", 0, "Diffuse", ""}, {SCE_PASS_GLOSSY_COLOR, "GLOSSY", 0, "Glossy", ""}, {SCE_PASS_TRANSM_COLOR, "TRANSMISSION", 0, "Transmission", ""}, - {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE", 0, "Subsurface", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -533,7 +532,7 @@ static void rna_def_render_engine(BlenderRNA *brna) 0, INT_MAX, "Pass Filter", - "Filter to combined, diffuse, glossy, transmission and subsurface passes", + "Filter to combined, diffuse, glossy and transmission passes", 0, INT_MAX); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index d2a17967de9..599b8fd91c8 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -526,7 +526,6 @@ const EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { {R_BAKE_PASS_FILTER_DIFFUSE, "DIFFUSE", 0, "Diffuse", ""}, {R_BAKE_PASS_FILTER_GLOSSY, "GLOSSY", 0, "Glossy", ""}, {R_BAKE_PASS_FILTER_TRANSM, "TRANSMISSION", 0, "Transmission", ""}, - {R_BAKE_PASS_FILTER_SUBSURFACE, "SUBSURFACE", 0, "Subsurface", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -3756,6 +3755,30 @@ static void rna_def_unit_settings(BlenderRNA *brna) RNA_def_property_update(prop, NC_WINDOW, NULL); } +static void rna_def_view_layer_eevee(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + srna = RNA_def_struct(brna, "ViewLayerEEVEE", NULL); + RNA_def_struct_ui_text(srna, "EEVEE Settings", "View layer settings for EEVEE"); + + prop = RNA_def_property(srna, "use_pass_volume_scatter", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_SCATTER); + RNA_def_property_ui_text(prop, "Volume Scatter", "Deliver volume scattering pass"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + + prop = RNA_def_property(srna, "use_pass_volume_transmittance", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "render_passes", EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE); + RNA_def_property_ui_text(prop, "Volume Transmittance", "Deliver volume transmittance pass"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); + + prop = RNA_def_property(srna, "use_pass_bloom", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "render_passes", EEVEE_RENDER_PASS_BLOOM); + RNA_def_property_ui_text(prop, "Bloom", "Deliver bloom pass"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, "rna_ViewLayer_pass_update"); +} + void rna_def_view_layer_common(StructRNA *srna, const bool scene) { PropertyRNA *prop; @@ -3801,6 +3824,11 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene) "Z, Index, normal, UV and vector passes are only affected by surfaces with " "alpha transparency equal to or higher than this threshold"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "eevee", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "ViewLayerEEVEE"); + RNA_def_property_ui_text(prop, "EEVEE Settings", "View layer settings for EEVEE"); } /* layer options */ @@ -4841,11 +4869,6 @@ static void rna_def_bake_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Transmission", "Add transmission contribution"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "use_pass_subsurface", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_SUBSURFACE); - RNA_def_property_ui_text(prop, "Subsurface", "Add subsurface contribution"); - RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "pass_filter", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "pass_filter"); RNA_def_property_enum_items(prop, rna_enum_bake_pass_filter_type_items); @@ -7546,6 +7569,7 @@ void RNA_def_scene(BlenderRNA *brna) rna_def_display_safe_areas(brna); rna_def_scene_display(brna); rna_def_scene_eevee(brna); + rna_def_view_layer_eevee(brna); RNA_define_animate_sdna(true); /* *** Animated *** */ rna_def_scene_render_data(brna); diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c index b0304b742df..89f65da335a 100644 --- a/source/blender/makesrna/intern/rna_screen.c +++ b/source/blender/makesrna/intern/rna_screen.c @@ -80,7 +80,7 @@ static void rna_Screen_redraw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), /* the settings for this are currently only available from a menu in the TimeLine, * hence refresh=SPACE_ACTION, as timeline is now in there */ - ED_screen_animation_timer_update(screen, screen->redraws_flag, SPACE_ACTION); + ED_screen_animation_timer_update(screen, screen->redraws_flag); } static bool rna_Screen_is_animation_playing_get(PointerRNA *UNUSED(ptr)) diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index fdea081d8f1..3d5d5091bf1 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -382,14 +382,32 @@ static const EnumPropertyItem rna_enum_studio_light_items[] = { }; static const EnumPropertyItem rna_enum_view3dshading_render_pass_type_items[] = { - {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, - /* {SCE_PASS_Z, "Z", 0, "Z", ""},*/ - {SCE_PASS_AO, "AO", 0, "Ambient Occlusion", ""}, - {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, - {SCE_PASS_MIST, "MIST", 0, "Mist", ""}, - {SCE_PASS_SUBSURFACE_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""}, - /* {SCE_PASS_SUBSURFACE_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""}, */ - {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""}, + {0, "", ICON_NONE, "General", ""}, + {EEVEE_RENDER_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, + {EEVEE_RENDER_PASS_EMIT, "EMISSION", 0, "Emission", ""}, + {EEVEE_RENDER_PASS_ENVIRONMENT, "ENVIRONMENT", 0, "Environment", ""}, + {EEVEE_RENDER_PASS_AO, "AO", 0, "Ambient Occlusion", ""}, + {EEVEE_RENDER_PASS_SHADOW, "SHADOW", 0, "Shadow", ""}, + + {0, "", ICON_NONE, "Light", ""}, + {EEVEE_RENDER_PASS_DIFFUSE_LIGHT, "DIFFUSE_LIGHT", 0, "Diffuse Light", ""}, + {EEVEE_RENDER_PASS_DIFFUSE_COLOR, "DIFFUSE_COLOR", 0, "Diffuse Color", ""}, + {EEVEE_RENDER_PASS_SPECULAR_LIGHT, "SPECULAR_LIGHT", 0, "Specular Light", ""}, + {EEVEE_RENDER_PASS_SPECULAR_COLOR, "SPECULAR_COLOR", 0, "Specular Color", ""}, + {EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE, + "VOLUME_TRANSMITTANCE", + 0, + "Volume Transmittance", + ""}, + {EEVEE_RENDER_PASS_VOLUME_SCATTER, "VOLUME_SCATTER", 0, "Volume Scattering", ""}, + + {0, "", ICON_NONE, "Effects", ""}, + {EEVEE_RENDER_PASS_BLOOM, "BLOOM", 0, "Bloom", ""}, + + {0, "", ICON_NONE, "Data", ""}, + {EEVEE_RENDER_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, + {EEVEE_RENDER_PASS_MIST, "MIST", 0, "Mist", ""}, + {0, NULL, 0, NULL, NULL}, }; @@ -1242,6 +1260,30 @@ static const EnumPropertyItem *rna_View3DShading_studio_light_itemf(bContext *UN return item; } +static const EnumPropertyItem *rna_3DViewShading_render_pass_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + Scene *scene = CTX_data_scene(C); + + const bool ao_enabled = scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED; + const bool bloom_enabled = scene->eevee.flag & SCE_EEVEE_BLOOM_ENABLED; + + int totitem = 0; + EnumPropertyItem *result = NULL; + for (int i = 0; rna_enum_view3dshading_render_pass_type_items[i].identifier != NULL; i++) { + const EnumPropertyItem *item = &rna_enum_view3dshading_render_pass_type_items[i]; + if (!((!ao_enabled && item->value == EEVEE_RENDER_PASS_AO) || + (!bloom_enabled && + (item->value == EEVEE_RENDER_PASS_BLOOM || STREQ(item->name, "Effects"))))) { + RNA_enum_item_add(&result, &totitem, item); + } + } + *r_free = true; + return result; +} + static void rna_SpaceView3D_use_local_collections_update(bContext *C, PointerRNA *ptr) { Main *bmain = CTX_data_main(C); @@ -3197,9 +3239,18 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) prop = RNA_def_property(srna, "studiolight_background_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "studiolight_background"); - RNA_def_property_ui_text(prop, "Background", "Show the studiolight in the background"); + RNA_def_property_ui_text(prop, "World Opacity", "Show the studiolight in the background"); RNA_def_property_range(prop, 0.0f, 1.0f); - RNA_def_property_ui_range(prop, 0.00f, 1.0f, 1, 3); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "studiolight_background_blur", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "studiolight_blur"); + RNA_def_property_ui_text(prop, "Blur", "Blur the studiolight in the background"); + RNA_def_property_float_default(prop, 0.5f); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 2); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); @@ -3328,6 +3379,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "render_pass"); RNA_def_property_enum_items(prop, rna_enum_view3dshading_render_pass_type_items); RNA_def_property_ui_text(prop, "Render Pass", "Render Pass to show in the viewport"); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_3DViewShading_render_pass_itemf"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 418fcfaf5f4..34f4fd45b9c 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2338,6 +2338,16 @@ static void rna_def_userdef_theme_space_graph(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "time_marker_line", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "time_marker_line_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line Selected", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "window_sliders", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "shade1"); RNA_def_property_array(prop, 3); @@ -3074,6 +3084,17 @@ static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "time_marker_line", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "time_marker_line_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line Selected", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "keyframe", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "vertex_select"); RNA_def_property_array(prop, 3); @@ -3142,6 +3163,17 @@ static void rna_def_userdef_theme_space_action(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "time_marker_line", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "time_marker_line_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line Selected", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "value_sliders", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "face"); RNA_def_property_array(prop, 3); @@ -3451,6 +3483,17 @@ static void rna_def_userdef_theme_space_nla(BlenderRNA *brna) RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "time_marker_line", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "time_marker_line_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line Selected", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + } static void rna_def_userdef_theme_colorset(BlenderRNA *brna) @@ -3571,6 +3614,17 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Scrubbing/Markers Region", ""); RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + prop = RNA_def_property(srna, "time_marker_line", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "time_marker_line_selected", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Marker Line Selected", ""); + RNA_def_property_update(prop, 0, "rna_userdef_theme_update"); + + prop = RNA_def_property(srna, "strips", PROP_FLOAT, PROP_COLOR_GAMMA); RNA_def_property_float_sdna(prop, NULL, "strip"); RNA_def_property_array(prop, 3); diff --git a/source/blender/nodes/composite/node_composite_tree.c b/source/blender/nodes/composite/node_composite_tree.c index 89349d91f94..93f2ba44a3a 100644 --- a/source/blender/nodes/composite/node_composite_tree.c +++ b/source/blender/nodes/composite/node_composite_tree.c @@ -281,8 +281,11 @@ void ntreeCompositUpdateRLayers(bNodeTree *ntree) } } -void ntreeCompositRegisterPass( - bNodeTree *ntree, Scene *scene, ViewLayer *view_layer, const char *name, int type) +void ntreeCompositRegisterPass(bNodeTree *ntree, + Scene *scene, + ViewLayer *view_layer, + const char *name, + eNodeSocketDatatype type) { bNode *node; diff --git a/source/blender/nodes/composite/nodes/node_composite_image.c b/source/blender/nodes/composite/nodes/node_composite_image.c index b74f325a3fa..f8a97868959 100644 --- a/source/blender/nodes/composite/nodes/node_composite_image.c +++ b/source/blender/nodes/composite/nodes/node_composite_image.c @@ -72,13 +72,14 @@ static bNodeSocketTemplate cmp_node_rlayers_out[] = { {SOCK_RGBA, 0, N_(RE_PASSNAME_SUBSURFACE_COLOR), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}, {-1, 0, ""}, }; +#define MAX_LEGACY_SOCKET_INDEX 30 static void cmp_node_image_add_pass_output(bNodeTree *ntree, bNode *node, const char *name, const char *passname, int rres_index, - int type, + eNodeSocketDatatype type, int is_rlayers, LinkNodePair *available_sockets, int *prev_index) @@ -94,8 +95,8 @@ static void cmp_node_image_add_pass_output(bNodeTree *ntree, * New sockets are placed behind the previously traversed one, * but always after the first 31. */ int after_index = *prev_index; - if (is_rlayers && after_index < 30) { - after_index = 30; + if (is_rlayers && after_index < MAX_LEGACY_SOCKET_INDEX) { + after_index = MAX_LEGACY_SOCKET_INDEX; } if (rres_index >= 0) { @@ -238,8 +239,12 @@ typedef struct RLayerUpdateData { int prev_index; } RLayerUpdateData; -void node_cmp_rlayers_register_pass( - bNodeTree *ntree, bNode *node, Scene *scene, ViewLayer *view_layer, const char *name, int type) +void node_cmp_rlayers_register_pass(bNodeTree *ntree, + bNode *node, + Scene *scene, + ViewLayer *view_layer, + const char *name, + eNodeSocketDatatype type) { RLayerUpdateData *data = node->storage; @@ -389,7 +394,7 @@ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node, bool rl break; } } - if (!link && (!rlayer || sock_index > 30)) { + if (!link && (!rlayer || sock_index > MAX_LEGACY_SOCKET_INDEX)) { MEM_freeN(sock->storage); nodeRemoveSocket(ntree, node, sock); } @@ -508,7 +513,7 @@ const char *node_cmp_rlayers_sock_to_pass(int sock_index) RE_PASSNAME_SUBSURFACE_INDIRECT, RE_PASSNAME_SUBSURFACE_COLOR, }; - if (sock_index > 30) { + if (sock_index > MAX_LEGACY_SOCKET_INDEX) { return NULL; } return sock_to_passname[sock_index]; diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c index 3fd627cd886..bee5377c438 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_rotate.c @@ -48,11 +48,6 @@ static int gpu_shader_vector_rotate(GPUMaterial *mat, [NODE_VECTOR_ROTATE_TYPE_AXIS_Y] = "node_vector_rotate_axis_y", [NODE_VECTOR_ROTATE_TYPE_AXIS_Z] = "node_vector_rotate_axis_z", [NODE_VECTOR_ROTATE_TYPE_EULER_XYZ] = "node_vector_rotate_euler_xyz", - [NODE_VECTOR_ROTATE_TYPE_EULER_XZY] = "node_vector_rotate_euler_xzy", - [NODE_VECTOR_ROTATE_TYPE_EULER_YXZ] = "node_vector_rotate_euler_yxz", - [NODE_VECTOR_ROTATE_TYPE_EULER_YZX] = "node_vector_rotate_euler_yzx", - [NODE_VECTOR_ROTATE_TYPE_EULER_ZXY] = "node_vector_rotate_euler_zxy", - [NODE_VECTOR_ROTATE_TYPE_EULER_ZYX] = "node_vector_rotate_euler_zyx", }; if (node->custom1 < ARRAY_SIZE(names) && names[node->custom1]) { @@ -66,21 +61,11 @@ static int gpu_shader_vector_rotate(GPUMaterial *mat, static void node_shader_update_vector_rotate(bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *sock_rotation = nodeFindSocket(node, SOCK_IN, "Rotation"); - nodeSetSocketAvailability(sock_rotation, - !ELEM(node->custom1, - NODE_VECTOR_ROTATE_TYPE_AXIS, - NODE_VECTOR_ROTATE_TYPE_AXIS_X, - NODE_VECTOR_ROTATE_TYPE_AXIS_Y, - NODE_VECTOR_ROTATE_TYPE_AXIS_Z)); + nodeSetSocketAvailability(sock_rotation, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); bNodeSocket *sock_axis = nodeFindSocket(node, SOCK_IN, "Axis"); nodeSetSocketAvailability(sock_axis, ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_AXIS)); bNodeSocket *sock_angle = nodeFindSocket(node, SOCK_IN, "Angle"); - nodeSetSocketAvailability(sock_angle, - ELEM(node->custom1, - NODE_VECTOR_ROTATE_TYPE_AXIS, - NODE_VECTOR_ROTATE_TYPE_AXIS_X, - NODE_VECTOR_ROTATE_TYPE_AXIS_Y, - NODE_VECTOR_ROTATE_TYPE_AXIS_Z)); + nodeSetSocketAvailability(sock_angle, !ELEM(node->custom1, NODE_VECTOR_ROTATE_TYPE_EULER_XYZ)); } void register_node_type_sh_vector_rotate(void) diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index a92be8509d5..a1dd9b3d5b0 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -86,10 +86,6 @@ if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() -if(WITH_MOD_FLUID) - add_definitions(-DWITH_FLUID) -endif() - if(WITH_FREESTYLE) list(APPEND INC ../freestyle diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 12e9123b5cb..88614de1641 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -26,6 +26,7 @@ #include "DNA_listBase.h" #include "DNA_scene_types.h" +#include "DNA_node_types.h" #include "RNA_types.h" #include "RE_bake.h" @@ -117,7 +118,7 @@ typedef void (*update_render_passes_cb_t)(void *userdata, const char *name, int channels, const char *chanid, - int type); + eNodeSocketDatatype type); typedef struct RenderEngine { RenderEngineType *type; @@ -212,7 +213,7 @@ void RE_engine_register_pass(struct RenderEngine *engine, const char *name, int channels, const char *chanid, - int type); + eNodeSocketDatatype type); /* Engine Types */ diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 90058da5f0c..598f300cf86 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -863,7 +863,7 @@ void RE_engine_register_pass(struct RenderEngine *engine, const char *name, int channels, const char *chanid, - int type) + eNodeSocketDatatype type) { if (!(scene && view_layer && engine && engine->update_render_passes_cb)) { return; diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 120787a8d13..b2225d70eaf 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -442,6 +442,15 @@ RenderResult *render_result_new(Render *re, if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) { RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_SUBSURFACE_COLOR, view, "RGB"); } + if (view_layer->eevee.render_passes & EEVEE_RENDER_PASS_BLOOM) { + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_BLOOM, view, "RGB"); + } + if (view_layer->eevee.render_passes & EEVEE_RENDER_PASS_VOLUME_SCATTER) { + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_VOLUME_SCATTER, view, "RGB"); + } + if (view_layer->eevee.render_passes & EEVEE_RENDER_PASS_VOLUME_TRANSMITTANCE) { + RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_VOLUME_TRANSMITTANCE, view, "RGB"); + } #undef RENDER_LAYER_ADD_PASS_SAFE } } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index eff5464c885..1775d9064d9 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -2808,7 +2808,7 @@ static uiBlock *block_create_autorun_warning(struct bContext *C, void *UNUSED(arg1)) { wmWindowManager *wm = CTX_wm_manager(C); - uiStyle *style = UI_style_get(); + uiStyle *style = UI_style_get_dpi(); uiBlock *block = UI_block_begin(C, ar, "autorun_warning_popup", UI_EMBOSS); UI_block_flag_enable( @@ -3067,6 +3067,7 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi /* Create dialog */ uiBlock *block = UI_block_begin(C, ar, close_file_dialog_name, UI_EMBOSS); + style = UI_style_get_dpi(); UI_block_flag_enable( block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 6e5068aa6b4..bc519055af3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1319,7 +1319,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) wmOperator *op = arg_op; uiBlock *block; uiLayout *layout; - uiStyle *style = UI_style_get(); + uiStyle *style = UI_style_get_dpi(); int width = 15 * UI_UNIT_X; block = UI_block_begin(C, ar, __func__, UI_EMBOSS); @@ -1401,7 +1401,7 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData) wmOperator *op = data->op; uiBlock *block; uiLayout *layout; - uiStyle *style = UI_style_get(); + uiStyle *style = UI_style_get_dpi(); block = UI_block_begin(C, ar, __func__, UI_EMBOSS); UI_block_flag_disable(block, UI_BLOCK_LOOP); @@ -1450,7 +1450,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData) wmOperator *op = data->op; uiBlock *block; uiLayout *layout; - uiStyle *style = UI_style_get(); + uiStyle *style = UI_style_get_dpi(); block = UI_block_begin(C, ar, __func__, UI_EMBOSS); UI_block_flag_disable(block, UI_BLOCK_LOOP); diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index 3603ce81654..7f6eebb95ab 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -259,7 +259,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar { uiBlock *block; uiBut *but; - uiStyle *style = UI_style_get(); + uiStyle *style = UI_style_get_dpi(); block = UI_block_begin(C, ar, "splash", UI_EMBOSS); diff --git a/source/blender/windowmanager/intern/wm_toolsystem.c b/source/blender/windowmanager/intern/wm_toolsystem.c index 616cb7613ba..e335800636c 100644 --- a/source/blender/windowmanager/intern/wm_toolsystem.c +++ b/source/blender/windowmanager/intern/wm_toolsystem.c @@ -374,6 +374,15 @@ void WM_toolsystem_ref_set_from_runtime(struct bContext *C, toolsystem_refresh_screen_from_active_tool(bmain, workspace, tref); + /* Set the cursor if possible, if not - it's fine as entering the region will refresh it. */ + { + wmWindow *win = CTX_wm_window(C); + if (win != NULL) { + win->addmousemove = true; + win->tag_cursor_refresh = true; + } + } + { struct wmMsgBus *mbus = CTX_wm_message_bus(C); WM_msg_publish_rna_prop(mbus, &workspace->id, workspace, WorkSpace, tools); diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt index 358200dece4..c47c7a5b4fc 100644 --- a/tests/python/CMakeLists.txt +++ b/tests/python/CMakeLists.txt @@ -183,6 +183,13 @@ add_blender_test( --run-all-tests ) +add_blender_test( + constraints + --python ${CMAKE_CURRENT_LIST_DIR}/bl_constraints.py + -- + --testdir "${TEST_SRC_DIR}/constraints" +) + # ------------------------------------------------------------------------------ # OPERATORS TESTS add_blender_test( diff --git a/tests/python/bl_constraints.py b/tests/python/bl_constraints.py new file mode 100644 index 00000000000..2a48ffe35ea --- /dev/null +++ b/tests/python/bl_constraints.py @@ -0,0 +1,204 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# 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. +# +# ##### END GPL LICENSE BLOCK ##### + +""" +./blender.bin --background -noaudio --factory-startup --python tests/python/bl_constraints.py -- --testdir /path/to/lib/tests/constraints +""" + +import pathlib +import sys +import unittest + +import bpy +from mathutils import Matrix + + +class AbstractConstraintTests(unittest.TestCase): + """Useful functionality for constraint tests.""" + + def setUp(self): + bpy.ops.wm.open_mainfile(filepath=str(args.testdir / "constraints.blend")) + + def assert_matrix(self, actual_matrix, expect_matrix, object_name: str, places=6, delta=None): + """Asserts that the matrices almost equal.""" + self.assertEqual(len(actual_matrix), 4, 'Expected a 4x4 matrix') + + # TODO(Sybren): decompose the matrices and compare loc, rot, and scale separately. + # That'll probably improve readability & understandability of test failures. + for row, (act_row, exp_row) in enumerate(zip(actual_matrix, expect_matrix)): + for col, (actual, expect) in enumerate(zip(act_row, exp_row)): + self.assertAlmostEqual( + actual, expect, places=places, delta=delta, + msg=f'Matrix of object {object_name!r} failed: {actual} != {expect} at element [{row}][{col}]') + + def matrix(self, object_name: str) -> Matrix: + """Return the evaluated world matrix.""" + depsgraph = bpy.context.view_layer.depsgraph + depsgraph.update() + ob_orig = bpy.context.scene.objects[object_name] + ob_eval = ob_orig.evaluated_get(depsgraph) + return ob_eval.matrix_world + + def matrix_test(self, object_name: str, expect: Matrix): + """Assert that the object's world matrix is as expected.""" + actual = self.matrix(object_name) + self.assert_matrix(actual, expect, object_name) + + def constraint_context(self, constraint_name: str, owner_name: str='') -> dict: + """Return a context suitable for calling constraint operators. + + Assumes the owner is called "{constraint_name}.owner" if owner_name=''. + """ + owner = bpy.context.scene.objects[owner_name or f'{constraint_name}.owner'] + constraint = owner.constraints[constraint_name] + context = { + **bpy.context.copy(), + 'object': owner, + 'active_object': owner, + 'constraint': constraint, + } + return context + + +class ChildOfTest(AbstractConstraintTests): + def test_object_simple_parent(self): + """Child Of: simple evaluation of object parent.""" + initial_matrix = Matrix(( + (0.5872668623924255, -0.3642929494380951, 0.29567837715148926, 1.0886117219924927), + (0.31689348816871643, 0.7095895409584045, 0.05480116978287697, 2.178966999053955), + (-0.21244174242019653, 0.06738340109586716, 0.8475662469863892, 3.2520291805267334), + (0.0, 0.0, 0.0, 1.0), + )) + self.matrix_test('Child Of.object.owner', initial_matrix) + + context = self.constraint_context('Child Of', owner_name='Child Of.object.owner') + bpy.ops.constraint.childof_set_inverse(context, constraint='Child Of') + self.matrix_test('Child Of.object.owner', Matrix(( + (0.9992385506629944, 0.019844001159071922, -0.03359175845980644, 0.10000011324882507), + (-0.01744179055094719, 0.997369647026062, 0.07035345584154129, 0.1999998837709427), + (0.034899525344371796, -0.06971397250890732, 0.9969563484191895, 0.3000001311302185), + (0.0, 0.0, 0.0, 1.0), + ))) + + bpy.ops.constraint.childof_clear_inverse(context, constraint='Child Of') + self.matrix_test('Child Of.object.owner', initial_matrix) + + def test_object_rotation_only(self): + """Child Of: rotation only.""" + owner = bpy.context.scene.objects['Child Of.object.owner'] + constraint = owner.constraints['Child Of'] + constraint.use_location_x = constraint.use_location_y = constraint.use_location_z = False + constraint.use_scale_x = constraint.use_scale_y = constraint.use_scale_z = False + + initial_matrix = Matrix(( + (0.8340795636177063, -0.4500490725040436, 0.31900957226753235, 0.10000000149011612), + (0.4547243118286133, 0.8883093595504761, 0.06428192555904388, 0.20000000298023224), + (-0.31230923533439636, 0.09144517779350281, 0.9455690383911133, 0.30000001192092896), + (0.0, 0.0, 0.0, 1.0), + )) + self.matrix_test('Child Of.object.owner', initial_matrix) + + context = self.constraint_context('Child Of', owner_name='Child Of.object.owner') + bpy.ops.constraint.childof_set_inverse(context, constraint='Child Of') + self.matrix_test('Child Of.object.owner', Matrix(( + (0.9992386102676392, 0.019843975082039833, -0.033591702580451965, 0.10000000149011612), + (-0.017441781237721443, 0.9973695874214172, 0.0703534483909607, 0.20000000298023224), + (0.03489946573972702, -0.06971397250890732, 0.9969563484191895, 0.30000001192092896), + (0.0, 0.0, 0.0, 1.0), + ))) + + bpy.ops.constraint.childof_clear_inverse(context, constraint='Child Of') + self.matrix_test('Child Of.object.owner', initial_matrix) + + def test_object_no_x_axis(self): + """Child Of: loc/rot/scale on only Y and Z axes.""" + owner = bpy.context.scene.objects['Child Of.object.owner'] + constraint = owner.constraints['Child Of'] + constraint.use_location_x = False + constraint.use_rotation_x = False + constraint.use_scale_x = False + + initial_matrix = Matrix(( + (0.8294582366943359, -0.4013831615447998, 0.2102886438369751, 0.10000000149011612), + (0.46277597546577454, 0.6895919442176819, 0.18639995157718658, 2.2317214012145996), + (-0.31224438548088074, -0.06574578583240509, 0.8546382784843445, 3.219514846801758), + (0.0, 0.0, 0.0, 1.0), + )) + self.matrix_test('Child Of.object.owner', initial_matrix) + + context = self.constraint_context('Child Of', owner_name='Child Of.object.owner') + bpy.ops.constraint.childof_set_inverse(context, constraint='Child Of') + self.matrix_test('Child Of.object.owner', Matrix(( + (0.9228900671005249, 0.23250490427017212, -0.035540513694286346, 0.10000000149011612), + (-0.011224273592233658, 0.9838480949401855, 0.24731633067131042, 0.21246682107448578), + (0.0383986234664917, -0.3163823187351227, 0.9553266167640686, 0.27248233556747437), + (0.0, 0.0, 0.0, 1.0), + ))) + + bpy.ops.constraint.childof_clear_inverse(context, constraint='Child Of') + self.matrix_test('Child Of.object.owner', initial_matrix) + + def test_bone_simple_parent(self): + """Child Of: simple evaluation of bone parent.""" + initial_matrix = Matrix(( + (0.5133683681488037, -0.06418320536613464, -0.014910104684531689, -0.2277737855911255), + (-0.03355155512690544, 0.12542974948883057, -1.080492377281189, 2.082599639892578), + (0.019313642755150795, 1.0446348190307617, 0.1244703009724617, 2.8542778491973877), + (0.0, 0.0, 0.0, 1.0), + )) + self.matrix_test('Child Of.armature.owner', initial_matrix) + + context = self.constraint_context('Child Of', owner_name='Child Of.armature.owner') + bpy.ops.constraint.childof_set_inverse(context, constraint='Child Of') + + self.matrix_test('Child Of.armature.owner', Matrix(( + (0.9992386102676392, 0.019843988120555878, -0.03359176218509674, 0.8358089923858643), + (-0.017441775649785995, 0.997369647026062, 0.0703534483909607, 1.7178752422332764), + (0.03489949554204941, -0.06971397995948792, 0.9969563484191895, -1.8132872581481934), + (0.0, 0.0, 0.0, 1.0), + ))) + + bpy.ops.constraint.childof_clear_inverse(context, constraint='Child Of') + self.matrix_test('Child Of.armature.owner', initial_matrix) + +def main(): + global args + import argparse + + if '--' in sys.argv: + argv = [sys.argv[0]] + sys.argv[sys.argv.index('--') + 1:] + else: + argv = sys.argv + + parser = argparse.ArgumentParser() + parser.add_argument('--testdir', required=True, type=pathlib.Path) + args, remaining = parser.parse_known_args(argv) + + unittest.main(argv=remaining) + + +if __name__ == "__main__": + import traceback + # So a python error exits Blender itself too + try: + main() + except SystemExit: + raise + except: + traceback.print_exc() + sys.exit(1) |