Compare commits
307 Commits
temp-chunk
...
tmp-drw-sp
Author | SHA1 | Date | |
---|---|---|---|
4847bcdbe1 | |||
520d111eca | |||
d2e576f34c | |||
10f1972ff7 | |||
f6c2f1c65e | |||
b70b02ee42 | |||
ffccdf069b | |||
6757f81fab | |||
db0ef8b00d | |||
5ffbabb24c | |||
1494a22a90 | |||
f1990bd900 | |||
fae975dd54 | |||
2fc136427d | |||
6d3da28676 | |||
![]() |
4bdba62cb9 | ||
039429faeb | |||
9be99bcb45 | |||
5dd48c50f0 | |||
46e0512d1e | |||
eeb81c4a63 | |||
a56da7b045 | |||
a66e584294 | |||
46076e4876 | |||
eab69d4930 | |||
0de9081e89 | |||
bbc69563d0 | |||
a4ff106c58 | |||
ff353842bd | |||
57620af33c | |||
0c282c068f | |||
f96020fb9a | |||
91db47e914 | |||
e2df195844 | |||
c64d3a692d | |||
c1548938a4 | |||
d459219307 | |||
ec8118a59e | |||
9cfa8b945a | |||
c087d09c16 | |||
0156a677c7 | |||
53ac3192ba | |||
65900d88a8 | |||
a790873d2a | |||
482d431bb6 | |||
25533dbe21 | |||
878dea4e0f | |||
6e9320d237 | |||
19955ef88e | |||
36096fe480 | |||
ad789c74df | |||
c55d38f00b | |||
2312915b96 | |||
8c95ab235f | |||
1f493125e3 | |||
3f55121a18 | |||
bb4e09ddc5 | |||
fe19de5fcc | |||
e191cf89b2 | |||
050b6498d3 | |||
808b03da43 | |||
5270ac5ed8 | |||
ada2b9f6e4 | |||
788f3d72cf | |||
5beaecb33e | |||
6d1d1bf2b1 | |||
72a7f107d8 | |||
6f9b84c5ce | |||
552561d46e | |||
5c93c37678 | |||
2ead05d738 | |||
b145cc9d36 | |||
f2bad0e49f | |||
aa58f58e46 | |||
2f0c40c7a2 | |||
b6ee599d92 | |||
![]() |
f69aaf71f8 | ||
447368b472 | |||
![]() |
2b88ee50fb | ||
fc604a0be3 | |||
![]() |
b0d70a9c80 | ||
12fdf9069a | |||
697e86a761 | |||
5f7259a001 | |||
![]() |
75a6d3abf7 | ||
6d19da0b2d | |||
![]() |
bd249eb4f3 | ||
![]() |
715c86d9e5 | ||
f3a46e2fd9 | |||
0084b8635f | |||
ed28ba4e99 | |||
f6664217b3 | |||
1cbfe04638 | |||
30113e54d2 | |||
4a60c4746d | |||
cbab734445 | |||
5f6d66c1c5 | |||
b6a7541f87 | |||
78952518e7 | |||
![]() |
cd7ec0dac6 | ||
2edb8ab739 | |||
4e1d32107b | |||
7fa7c7ceda | |||
![]() |
8da253cfb6 | ||
dcd909122f | |||
722b850c38 | |||
408a8edf89 | |||
b77ad0c82d | |||
cd1caa5853 | |||
![]() |
66a863e301 | ||
bcb7b119ae | |||
cd7e9a1ad5 | |||
84ddb8b3cc | |||
57ea827bfb | |||
8d49a4f36e | |||
d4fc451b90 | |||
ddf6f70049 | |||
c15a761524 | |||
837144b457 | |||
8a6dc0fac7 | |||
46cfd345e4 | |||
236fda7faf | |||
125ac1f914 | |||
![]() |
2522ca03d2 | ||
2356afc7af | |||
03eac69c61 | |||
b211540783 | |||
fa1c214c5b | |||
530b9841ee | |||
333e41eac6 | |||
0210c4df17 | |||
6075b04cf9 | |||
267aee514a | |||
b4605f6158 | |||
34477bbfcd | |||
6275541df7 | |||
96d88e5614 | |||
20276191e5 | |||
3961d3493b | |||
3a7dc572dc | |||
5b320e5a24 | |||
8a68f4f808 | |||
15f3cf7f8f | |||
e746999aa9 | |||
b3714b1e85 | |||
c8ee70c962 | |||
2fd63efd0e | |||
c6e70e7bac | |||
0419ee871f | |||
21d77a417e | |||
d35a10134c | |||
b6adca3280 | |||
f68cfd6bb0 | |||
c7b247a118 | |||
891949cbb4 | |||
c9e35c2ced | |||
865894481c | |||
26f330ea4c | |||
4e7983e073 | |||
2ff5d42cd3 | |||
72933ebe96 | |||
1b46d57f67 | |||
535f50e5a6 | |||
c25df02ac3 | |||
8422da13c9 | |||
f416a76bcd | |||
cd1631b17d | |||
88a602bc64 | |||
ff27b68f41 | |||
ce63fea080 | |||
1b5c94630e | |||
fd2668a368 | |||
c2a21dfb77 | |||
7e980f2b8c | |||
dedc679eca | |||
d5554cdc7c | |||
d12f0d3f70 | |||
392855ce50 | |||
2d8eadacf9 | |||
67308d73a4 | |||
2438f76d6f | |||
12becbf0df | |||
e345686cb7 | |||
63bdd89108 | |||
a8a454287a | |||
b197cd5821 | |||
0d7d8c73cf | |||
060a534141 | |||
35375380d7 | |||
998fc4f8f6 | |||
f2b5fd0a0e | |||
e5d4afd5ba | |||
eb54502d9d | |||
c350d97a2f | |||
fbd78a8d78 | |||
c655bdfa31 | |||
77ed4651ee | |||
0f6d5c9a9d | |||
c172522060 | |||
0e94d24080 | |||
187d8ba362 | |||
998ace3463 | |||
add1b6ab3c | |||
3edd87f009 | |||
cda2dc721d | |||
e9344d329f | |||
319ee296fd | |||
![]() |
680fa8a523 | ||
![]() |
e8bcca4bdc | ||
![]() |
18b45aabf9 | ||
![]() |
1514e1a5b7 | ||
![]() |
697b447c20 | ||
![]() |
bb63b98d1f | ||
dd5131bd70 | |||
dc06bf2cb6 | |||
![]() |
0c824837ab | ||
75d984a712 | |||
c50335b359 | |||
3185c3bc74 | |||
ef06375159 | |||
7ce09ef48f | |||
967fe75bb6 | |||
62ffbc7d7f | |||
20dc839319 | |||
77dcfac8a3 | |||
3676d6b88d | |||
f42569bb71 | |||
91dd29fd45 | |||
600c069e0e | |||
a82e52102b | |||
c1f622e63e | |||
a2966f6477 | |||
8bffadcdc4 | |||
cd3a19f20c | |||
0ca9b637c5 | |||
f948ffaa9f | |||
78b7a1c3a8 | |||
1b95784aad | |||
efa6525bf1 | |||
cd84d3f3da | |||
![]() |
6adb481fb5 | ||
78bfaf1a4f | |||
15593299f3 | |||
ae21319d7f | |||
bc88f2006d | |||
ea79dab062 | |||
f97728248e | |||
5517c848bd | |||
e9bdf8ebc3 | |||
6f15141f27 | |||
cbbed90486 | |||
7f284f5134 | |||
1df58ec540 | |||
90999a0694 | |||
01ed08690a | |||
9df0d20957 | |||
ed6c8d82b8 | |||
1b4cf3af4b | |||
![]() |
01a4d38606 | ||
32b766223a | |||
bf14757709 | |||
5c33704ffa | |||
afe91903af | |||
![]() |
3132d2751e | ||
![]() |
1f828a5a06 | ||
9396437417 | |||
2b4cb893e7 | |||
22efaa2e7b | |||
5c81d3bd46 | |||
7a239812ca | |||
c8a18fd239 | |||
41935b9285 | |||
22b69ed08f | |||
e00f76c6a8 | |||
b950a8fb79 | |||
c279a0d931 | |||
09308c4b6a | |||
9c35f103c0 | |||
710b8b7929 | |||
3d5e0c8b9d | |||
a24fc6bbc1 | |||
7a67d69ca4 | |||
bdb5754147 | |||
862de9187f | |||
![]() |
b6e26a410c | ||
0e6a8df6df | |||
5c13c7cd30 | |||
be863506b8 | |||
2ce8b01c59 | |||
2fffd7d7a8 | |||
327802b86f | |||
2c407cfb8f | |||
ea35c237fc | |||
6b8b2c8e7f | |||
6424fbca94 | |||
4baa6e57bd | |||
![]() |
8a9f6a2e0a | ||
a45b408422 | |||
ecf3435362 | |||
7536abbe16 | |||
cf56b8be37 | |||
53c92efd5a | |||
998ffcbf09 | |||
fd1bc90679 | |||
0ffd288fab | |||
6bf5cc62e0 | |||
892a5f8176 |
310
CMakeLists.txt
310
CMakeLists.txt
@@ -111,6 +111,25 @@ blender_project_hack_post()
|
||||
enable_testing()
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Test Compiler Support
|
||||
#
|
||||
# Keep in sync with: https://wiki.blender.org/wiki/Building_Blender
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if("${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "9.3.1")
|
||||
message(FATAL_ERROR "The minimum supported version of GCC is 9.3.1")
|
||||
endif()
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND ("${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "8.0"))
|
||||
message(FATAL_ERROR "The minimum supported version of CLANG is 8.0")
|
||||
endif()
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
if(MSVC_VERSION VERSION_LESS "1928")
|
||||
message(FATAL_ERROR "The minimum supported version of MSVC is 2019 (16.9.16)")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Test Compiler/Library Features
|
||||
|
||||
@@ -410,6 +429,7 @@ mark_as_advanced(WITH_CPU_SIMD)
|
||||
# Cycles
|
||||
option(WITH_CYCLES "Enable Cycles Render Engine" ON)
|
||||
option(WITH_CYCLES_OSL "Build Cycles with OpenShadingLanguage support" ON)
|
||||
option(WITH_CYCLES_PATH_GUIDING "Build Cycles with path guiding support" ON)
|
||||
option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" ON)
|
||||
option(WITH_CYCLES_LOGGING "Build Cycles with logging support" ON)
|
||||
option(WITH_CYCLES_DEBUG "Build Cycles with options useful for debugging (e.g., MIS)" OFF)
|
||||
@@ -628,8 +648,8 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
unset(_asan_defaults)
|
||||
|
||||
if(MSVC)
|
||||
find_library(
|
||||
COMPILER_ASAN_LIBRARY NAMES clang_rt.asan-x86_64
|
||||
find_library(
|
||||
COMPILER_ASAN_LIBRARY NAMES clang_rt.asan-x86_64
|
||||
PATHS
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/7.0.0/lib/windows
|
||||
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\LLVM\\LLVM;]/lib/clang/6.0.0/lib/windows
|
||||
@@ -808,7 +828,7 @@ endif()
|
||||
set_and_warn_dependency(WITH_PUGIXML WITH_OPENIMAGEIO OFF)
|
||||
|
||||
if(WITH_BOOST AND NOT (WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
|
||||
WITH_OPENVDB OR WITH_OPENCOLORIO OR WITH_USD OR WITH_ALEMBIC))
|
||||
WITH_OPENVDB OR WITH_OPENCOLORIO OR WITH_USD OR WITH_ALEMBIC))
|
||||
message(STATUS "No dependencies need 'WITH_BOOST' forcing WITH_BOOST=OFF")
|
||||
set(WITH_BOOST OFF)
|
||||
endif()
|
||||
@@ -1022,9 +1042,9 @@ if(WITH_CPU_SIMD)
|
||||
set(COMPILER_SSE2_FLAG)
|
||||
|
||||
# Test Neon first since macOS Arm can compile and run x86-64 SSE binaries.
|
||||
TEST_NEON_SUPPORT()
|
||||
test_neon_support()
|
||||
if(NOT SUPPORT_NEON_BUILD)
|
||||
TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
|
||||
test_sse_support(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1089,7 +1109,7 @@ if(WITH_INTERNATIONAL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Enable SIMD support if detected by TEST_SSE_SUPPORT() or TEST_NEON_SUPPORT().
|
||||
# Enable SIMD support if detected by `test_sse_support()` or `test_neon_support()`.
|
||||
#
|
||||
# This is done globally, so that all modules can use it if available, and
|
||||
# because these are used in headers used by many modules.
|
||||
@@ -1097,7 +1117,7 @@ if(WITH_CPU_SIMD)
|
||||
if(SUPPORT_NEON_BUILD)
|
||||
# Neon
|
||||
if(SSE2NEON_FOUND)
|
||||
blender_include_dirs_sys("${SSE2NEON_INCLUDE_DIRS}")
|
||||
include_directories(SYSTEM "${SSE2NEON_INCLUDE_DIRS}")
|
||||
add_definitions(-DWITH_SSE2NEON)
|
||||
endif()
|
||||
else()
|
||||
@@ -1271,7 +1291,11 @@ endif()
|
||||
# Configure Python
|
||||
|
||||
if(WITH_PYTHON_MODULE)
|
||||
add_definitions(-DPy_ENABLE_SHARED)
|
||||
# Not currently supported due to different required Python link flags.
|
||||
if(WITH_GTESTS)
|
||||
message(STATUS "GTests not compatible with Python module, disabling WITH_GTESTS")
|
||||
set(WITH_GTESTS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1399,91 +1423,75 @@ endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ALL -Wall)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_RETURN_TYPE -Werror=return-type)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_VLA -Werror=vla)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ALL -Wall)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ERROR_RETURN_TYPE -Werror=return-type)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ERROR_VLA -Werror=vla)
|
||||
# system headers sometimes do this, disable for now, was: -Werror=strict-prototypes
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_WRITE_STRINGS -Wwrite-strings)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_LOGICAL_OP -Wlogical-op)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEF -Wundef)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_TYPE_LIMITS -Wtype-limits)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_FORMAT_SIGN -Wformat-signedness)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_RESTRICT -Wrestrict)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_WRITE_STRINGS -Wwrite-strings)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_LOGICAL_OP -Wlogical-op)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_UNDEF -Wundef)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_TYPE_LIMITS -Wtype-limits)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_FORMAT_SIGN -Wformat-signedness)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_RESTRICT -Wrestrict)
|
||||
|
||||
# C-only.
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_NULL -Wnonnull)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ABSOLUTE_VALUE -Wabsolute-value)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_NULL -Wnonnull)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ABSOLUTE_VALUE -Wabsolute-value)
|
||||
|
||||
# gcc 4.2 gives annoying warnings on every file with this
|
||||
if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized)
|
||||
endif()
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized)
|
||||
|
||||
# versions before gcc4.6 give many BLI_math warnings
|
||||
if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.6")
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_REDUNDANT_DECLS -Wredundant-decls)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_REDUNDANT_DECLS -Wredundant-decls)
|
||||
endif()
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_REDUNDANT_DECLS -Wredundant-decls)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_REDUNDANT_DECLS -Wredundant-decls)
|
||||
|
||||
# versions before gcc4.8 include global name-space.
|
||||
if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.8")
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_SHADOW -Wshadow)
|
||||
endif()
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_SHADOW -Wshadow)
|
||||
|
||||
# disable because it gives warnings for printf() & friends.
|
||||
# ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_DOUBLE_PROMOTION -Wdouble-promotion -Wno-error=double-promotion)
|
||||
# add_check_c_compiler_flag(C_WARNINGS C_WARN_DOUBLE_PROMOTION -Wdouble-promotion -Wno-error=double-promotion)
|
||||
|
||||
if(NOT APPLE)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
|
||||
endif()
|
||||
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_LOGICAL_OP -Wlogical-op)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_TYPE_LIMITS -Wtype-limits)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ERROR_RETURN_TYPE -Werror=return-type)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_POINTER_ARITH -Wpointer-arith)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_PARAMETER -Wunused-parameter)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_WRITE_STRINGS -Wwrite-strings)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEF -Wundef)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_FORMAT_SIGN -Wformat-signedness)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_RESTRICT -Wrestrict)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SUGGEST_OVERRIDE -Wno-suggest-override)
|
||||
|
||||
# gcc 4.2 gives annoying warnings on every file with this
|
||||
if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3")
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized)
|
||||
endif()
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_ALL -Wall)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_LOGICAL_OP -Wlogical-op)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_INIT_SELF -Winit-self) # needs -Wuninitialized
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_MISSING_INCLUDE_DIRS -Wmissing-include-dirs)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_DIV_BY_ZERO -Wno-div-by-zero)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_TYPE_LIMITS -Wtype-limits)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_ERROR_RETURN_TYPE -Werror=return-type)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_POINTER_ARITH -Wpointer-arith)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_UNUSED_PARAMETER -Wunused-parameter)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_WRITE_STRINGS -Wwrite-strings)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_UNDEF -Wundef)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_FORMAT_SIGN -Wformat-signedness)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_RESTRICT -Wrestrict)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_SUGGEST_OVERRIDE -Wno-suggest-override)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized)
|
||||
|
||||
# causes too many warnings
|
||||
if(NOT APPLE)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEF -Wundef)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_MISSING_DECLARATIONS -Wmissing-declarations)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_UNDEF -Wundef)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_MISSING_DECLARATIONS -Wmissing-declarations)
|
||||
endif()
|
||||
|
||||
# Use 'ATTR_FALLTHROUGH' macro to suppress.
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "7.0"))
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_IMPLICIT_FALLTHROUGH -Wimplicit-fallthrough=5)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_IMPLICIT_FALLTHROUGH -Wimplicit-fallthrough=5)
|
||||
endif()
|
||||
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_IMPLICIT_FALLTHROUGH -Wimplicit-fallthrough=5)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_IMPLICIT_FALLTHROUGH -Wimplicit-fallthrough=5)
|
||||
|
||||
# ---------------------
|
||||
# Suppress Strict Flags
|
||||
@@ -1497,102 +1505,100 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
# If code in `./extern/` needs to suppress these flags that can be done on a case-by-case basis.
|
||||
|
||||
# flags to undo strict flags
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_TYPE_LIMITS -Wno-type-limits)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_INT_IN_BOOL_CONTEXT -Wno-int-in-bool-context)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_FORMAT -Wno-format)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_SWITCH -Wno-switch)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-uninitialized)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_TYPE_LIMITS -Wno-type-limits)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_INT_IN_BOOL_CONTEXT -Wno-int-in-bool-context)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_FORMAT -Wno-format)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_SWITCH -Wno-switch)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-uninitialized)
|
||||
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_CLASS_MEMACCESS -Wno-class-memaccess)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_COMMENT -Wno-comment)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_TYPEDEFS -Wno-unused-local-typedefs)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-uninitialized)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_CLASS_MEMACCESS -Wno-class-memaccess)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_COMMENT -Wno-comment)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_TYPEDEFS -Wno-unused-local-typedefs)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-uninitialized)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "7.0"))
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_IMPLICIT_FALLTHROUGH -Wno-implicit-fallthrough)
|
||||
endif()
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_IMPLICIT_FALLTHROUGH -Wno-implicit-fallthrough)
|
||||
|
||||
if(NOT APPLE)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
|
||||
endif()
|
||||
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
|
||||
# strange, clang complains these are not supported, but then uses them.
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ALL -Wall)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ERROR_RETURN_TYPE -Werror=return-type)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ALL -Wall)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ERROR_IMPLICIT_FUNCTION_DECLARATION -Werror=implicit-function-declaration)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ERROR_RETURN_TYPE -Werror=return-type)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_STRICT_PROTOTYPES -Wstrict-prototypes)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_MISSING_PROTOTYPES -Wmissing-prototypes)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
|
||||
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_ALL -Wall)
|
||||
# Using C++20 features while having C++17 as the project language isn't allowed by MSVC.
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_CXX20_DESIGNATOR -Wc++20-designator)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_CXX20_DESIGNATOR -Wc++20-designator)
|
||||
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_OVERLOADED_VIRTUAL -Wno-overloaded-virtual) # we get a lot of these, if its a problem a dev needs to look into it.
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_AUTOLOGICAL_COMPARE -Wno-tautological-compare)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_CHAR_SUBSCRIPTS -Wno-char-subscripts)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_OVERLOADED_VIRTUAL -Wno-overloaded-virtual) # we get a lot of these, if its a problem a dev needs to look into it.
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
# Apple Clang (tested on version 12) doesn't support this flag while LLVM Clang 11 does.
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SUGGEST_OVERRIDE -Wno-suggest-override)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_SUGGEST_OVERRIDE -Wno-suggest-override)
|
||||
|
||||
# gives too many unfixable warnings
|
||||
# ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_MACROS -Wunused-macros)
|
||||
# ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros)
|
||||
# add_check_c_compiler_flag(C_WARNINGS C_WARN_UNUSED_MACROS -Wunused-macros)
|
||||
# add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_UNUSED_MACROS -Wunused-macros)
|
||||
|
||||
# ---------------------
|
||||
# Suppress Strict Flags
|
||||
|
||||
# flags to undo strict flags
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISLEADING_INDENTATION -Wno-misleading-indentation)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISLEADING_INDENTATION -Wno-misleading-indentation)
|
||||
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_VARIABLE_DECLARATIONS -Wno-missing-variable-declarations)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_INCOMPAT_PTR_DISCARD_QUAL -Wno-incompatible-pointer-types-discards-qualifiers)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_INT_TO_VOID_POINTER_CAST -Wno-int-to-void-pointer-cast)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_PROTOTYPES -Wno-missing-prototypes)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DUPLICATE_ENUM -Wno-duplicate-enum)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNDEF -Wno-undef)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_NORETURN -Wno-missing-noreturn)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_BUT_SET_VARIABLE -Wno-unused-but-set-variable)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_VARIABLE_DECLARATIONS -Wno-missing-variable-declarations)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_INCOMPAT_PTR_DISCARD_QUAL -Wno-incompatible-pointer-types-discards-qualifiers)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_FUNCTION -Wno-unused-function)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_INT_TO_VOID_POINTER_CAST -Wno-int-to-void-pointer-cast)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_PROTOTYPES -Wno-missing-prototypes)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_DUPLICATE_ENUM -Wno-duplicate-enum)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNDEF -Wno-undef)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_MISSING_NORETURN -Wno-missing-noreturn)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_BUT_SET_VARIABLE -Wno-unused-but-set-variable)
|
||||
add_check_c_compiler_flag(C_REMOVE_STRICT_FLAGS C_WARN_NO_DEPRECATED_DECLARATIONS -Wno-deprecated-declarations)
|
||||
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PRIVATE_FIELD -Wno-unused-private-field)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_CXX11_NARROWING -Wno-c++11-narrowing)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_NON_VIRTUAL_DTOR -Wno-non-virtual-dtor)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_REORDER -Wno-reorder)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_COMMENT -Wno-comment)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_TYPEDEFS -Wno-unused-local-typedefs)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNDEFINED_VAR_TEMPLATE -Wno-undefined-var-template)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_INSTANTIATION_AFTER_SPECIALIZATION -Wno-instantiation-after-specialization)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_MISLEADING_INDENTATION -Wno-misleading-indentation)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PARAMETER -Wno-unused-parameter)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_PRIVATE_FIELD -Wno-unused-private-field)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_CXX11_NARROWING -Wno-c++11-narrowing)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_NON_VIRTUAL_DTOR -Wno-non-virtual-dtor)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_MACROS -Wno-unused-macros)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_REORDER -Wno-reorder)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_COMMENT -Wno-comment)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_TYPEDEFS -Wno-unused-local-typedefs)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNDEFINED_VAR_TEMPLATE -Wno-undefined-var-template)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_INSTANTIATION_AFTER_SPECIALIZATION -Wno-instantiation-after-specialization)
|
||||
add_check_cxx_compiler_flag(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_MISLEADING_INDENTATION -Wno-misleading-indentation)
|
||||
|
||||
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
|
||||
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_ALL -Wall)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith)
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_ALL -Wall)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith)
|
||||
add_check_c_compiler_flag(C_WARNINGS C_WARN_NO_UNKNOWN_PRAGMAS -Wno-unknown-pragmas)
|
||||
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_ALL -Wall)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
|
||||
add_check_cxx_compiler_flag(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
|
||||
|
||||
# disable numbered, false positives
|
||||
string(APPEND C_WARNINGS " -wd188,186,144,913,556,858,597,177,1292,167,279,592,94,2722,3199")
|
||||
@@ -1605,6 +1611,8 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||
"/w34062" # switch statement contains 'default' but no 'case' labels
|
||||
"/w34115" # 'type' : named type definition in parentheses
|
||||
"/w34189" # local variable is initialized but not referenced
|
||||
# see https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/c5038?view=vs-2017
|
||||
"/w35038" # order of initialization in c++ constructors
|
||||
# disable:
|
||||
"/wd4018" # signed/unsigned mismatch
|
||||
"/wd4146" # unary minus operator applied to unsigned type, result still unsigned
|
||||
@@ -1624,13 +1632,9 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||
"/we4013" # 'function' undefined; assuming extern returning int
|
||||
"/we4133" # incompatible pointer types
|
||||
"/we4431" # missing type specifier - int assumed
|
||||
"/we4033" # 'function' must return a value
|
||||
)
|
||||
|
||||
if(MSVC_VERSION GREATER_EQUAL 1911)
|
||||
# see https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/c5038?view=vs-2017
|
||||
string(APPEND _WARNINGS " /w35038") # order of initialization in c++ constructors
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" " " _WARNINGS "${_WARNINGS}")
|
||||
set(C_WARNINGS "${_WARNINGS}")
|
||||
set(CXX_WARNINGS "${_WARNINGS}")
|
||||
@@ -1682,7 +1686,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
# Make MSVC properly report the value of the __cplusplus preprocessor macro
|
||||
# Available MSVC 15.7 (1914) and up, without this it reports 199711L regardless
|
||||
# of the C++ standard chosen above.
|
||||
if(MSVC AND MSVC_VERSION GREATER 1913)
|
||||
if(MSVC)
|
||||
string(APPEND CMAKE_CXX_FLAGS " /Zc:__cplusplus")
|
||||
endif()
|
||||
|
||||
@@ -1705,8 +1709,8 @@ endif()
|
||||
|
||||
if(WITH_COMPILER_SHORT_FILE_MACRO)
|
||||
# Use '-fmacro-prefix-map' for Clang and GCC (MSVC doesn't support this).
|
||||
ADD_CHECK_C_COMPILER_FLAG(C_PREFIX_MAP_FLAGS C_MACRO_PREFIX_MAP -fmacro-prefix-map=foo=bar)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CXX_PREFIX_MAP_FLAGS CXX_MACRO_PREFIX_MAP -fmacro-prefix-map=foo=bar)
|
||||
add_check_c_compiler_flag(C_PREFIX_MAP_FLAGS C_MACRO_PREFIX_MAP -fmacro-prefix-map=foo=bar)
|
||||
add_check_cxx_compiler_flag(CXX_PREFIX_MAP_FLAGS CXX_MACRO_PREFIX_MAP -fmacro-prefix-map=foo=bar)
|
||||
if(C_MACRO_PREFIX_MAP AND CXX_MACRO_PREFIX_MAP)
|
||||
if(APPLE)
|
||||
if(XCODE AND ${XCODE_VERSION} VERSION_LESS 12.0)
|
||||
|
@@ -364,7 +364,7 @@ all: .FORCE
|
||||
$(BUILD_COMMAND) -C "$(BUILD_DIR)" -j $(NPROCS) install
|
||||
@echo
|
||||
@echo Edit build configuration with: \"$(BUILD_DIR)/CMakeCache.txt\" run make again to rebuild.
|
||||
@if test "$(BLENDER_IS_PYTHON_MODULE)" == ""; then \
|
||||
@if test -z "$(BLENDER_IS_PYTHON_MODULE)"; then \
|
||||
echo Blender successfully built, run from: $(BLENDER_BIN); \
|
||||
else \
|
||||
echo Blender successfully built as a Python module, \"bpy\" can be imported from: $(BLENDER_BIN_DIR); \
|
||||
|
@@ -94,6 +94,7 @@ include(cmake/pugixml.cmake)
|
||||
include(cmake/ispc.cmake)
|
||||
include(cmake/openimagedenoise.cmake)
|
||||
include(cmake/embree.cmake)
|
||||
include(cmake/openpgl.cmake)
|
||||
include(cmake/fmt.cmake)
|
||||
include(cmake/robinmap.cmake)
|
||||
if(NOT APPLE)
|
||||
@@ -169,6 +170,8 @@ if(UNIX AND NOT APPLE)
|
||||
include(cmake/libglu.cmake)
|
||||
include(cmake/mesa.cmake)
|
||||
include(cmake/wayland_protocols.cmake)
|
||||
# Can be removed when the build-bot upgrades to v1.20.x or newer.
|
||||
include(cmake/wayland.cmake)
|
||||
endif()
|
||||
|
||||
include(cmake/harvest.cmake)
|
||||
|
@@ -89,6 +89,7 @@ download_source(MESA)
|
||||
download_source(NASM)
|
||||
download_source(XR_OPENXR_SDK)
|
||||
download_source(WL_PROTOCOLS)
|
||||
download_source(WAYLAND)
|
||||
download_source(ISPC)
|
||||
download_source(GMP)
|
||||
download_source(POTRACE)
|
||||
@@ -101,6 +102,7 @@ download_source(FMT)
|
||||
download_source(ROBINMAP)
|
||||
download_source(IMATH)
|
||||
download_source(PYSTRING)
|
||||
download_source(OPENPGL)
|
||||
download_source(LEVEL_ZERO)
|
||||
download_source(DPCPP)
|
||||
download_source(VCINTRINSICS)
|
||||
|
@@ -68,7 +68,7 @@ set(DPCPP_EXTRA_ARGS
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND DPCPP_EXTRA_ARGS -DPython3_FIND_REGISTRY=NEVER)
|
||||
list(APPEND DPCPP_EXTRA_ARGS -DPython3_FIND_REGISTRY=NEVER)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_dpcpp
|
||||
|
@@ -11,188 +11,192 @@ message("HARVEST_TARGET = ${HARVEST_TARGET}")
|
||||
|
||||
if(WIN32)
|
||||
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
add_custom_target(Harvest_Release_Results
|
||||
COMMAND # jpeg rename libfile + copy include
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/jpeg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpeg/include/ ${HARVEST_TARGET}/jpeg/include/ &&
|
||||
# png
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static.lib ${HARVEST_TARGET}/png/lib/libpng.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ &&
|
||||
# freeglut-> opengl
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/freeglut/lib/freeglut_static.lib ${HARVEST_TARGET}/opengl/lib/freeglut_static.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freeglut/include/ ${HARVEST_TARGET}/opengl/include/ &&
|
||||
DEPENDS
|
||||
)
|
||||
endif()
|
||||
|
||||
else(WIN32)
|
||||
|
||||
function(harvest from to)
|
||||
set(pattern "")
|
||||
foreach(f ${ARGN})
|
||||
set(pattern ${f})
|
||||
endforeach()
|
||||
|
||||
if(pattern STREQUAL "")
|
||||
get_filename_component(dirpath ${to} DIRECTORY)
|
||||
get_filename_component(filename ${to} NAME)
|
||||
install(
|
||||
FILES ${LIBDIR}/${from}
|
||||
DESTINATION ${HARVEST_TARGET}/${dirpath}
|
||||
RENAME ${filename}
|
||||
)
|
||||
else()
|
||||
install(
|
||||
DIRECTORY ${LIBDIR}/${from}/
|
||||
DESTINATION ${HARVEST_TARGET}/${to}
|
||||
USE_SOURCE_PERMISSIONS
|
||||
FILES_MATCHING PATTERN ${pattern}
|
||||
PATTERN "pkgconfig" EXCLUDE
|
||||
PATTERN "cmake" EXCLUDE
|
||||
PATTERN "__pycache__" EXCLUDE
|
||||
PATTERN "tests" EXCLUDE
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
add_custom_target(Harvest_Release_Results
|
||||
COMMAND # jpeg rename libfile + copy include
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/jpeg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpeg/include/ ${HARVEST_TARGET}/jpeg/include/ &&
|
||||
# png
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static.lib ${HARVEST_TARGET}/png/lib/libpng.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ &&
|
||||
# freeglut-> opengl
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/freeglut/lib/freeglut_static.lib ${HARVEST_TARGET}/opengl/lib/freeglut_static.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/freeglut/include/ ${HARVEST_TARGET}/opengl/include/ &&
|
||||
DEPENDS
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
harvest(alembic/include alembic/include "*.h")
|
||||
harvest(alembic/lib/libAlembic.a alembic/lib/libAlembic.a)
|
||||
harvest(alembic/bin alembic/bin "*")
|
||||
harvest(brotli/include brotli/include "*.h")
|
||||
harvest(brotli/lib brotli/lib "*.a")
|
||||
harvest(boost/include boost/include "*")
|
||||
harvest(boost/lib boost/lib "*.a")
|
||||
harvest(imath/include imath/include "*.h")
|
||||
harvest(imath/lib imath/lib "*.a")
|
||||
harvest(ffmpeg/include ffmpeg/include "*.h")
|
||||
harvest(ffmpeg/lib ffmpeg/lib "*.a")
|
||||
harvest(fftw3/include fftw3/include "*.h")
|
||||
harvest(fftw3/lib fftw3/lib "*.a")
|
||||
harvest(flac/lib sndfile/lib "libFLAC.a")
|
||||
harvest(freetype/include freetype/include "*.h")
|
||||
harvest(freetype/lib/libfreetype2ST.a freetype/lib/libfreetype.a)
|
||||
harvest(epoxy/include epoxy/include "*.h")
|
||||
harvest(epoxy/lib epoxy/lib "*.a")
|
||||
harvest(gmp/include gmp/include "*.h")
|
||||
harvest(gmp/lib gmp/lib "*.a")
|
||||
harvest(jemalloc/include jemalloc/include "*.h")
|
||||
harvest(jemalloc/lib jemalloc/lib "*.a")
|
||||
harvest(jpeg/include jpeg/include "*.h")
|
||||
harvest(jpeg/lib jpeg/lib "libjpeg.a")
|
||||
harvest(lame/lib ffmpeg/lib "*.a")
|
||||
if(NOT APPLE)
|
||||
harvest(level-zero/include/level_zero level-zero/include/level_zero "*.h")
|
||||
harvest(level-zero/lib level-zero/lib "*.so*")
|
||||
endif()
|
||||
harvest(llvm/bin llvm/bin "clang-format")
|
||||
if(BUILD_CLANG_TOOLS)
|
||||
harvest(llvm/bin llvm/bin "clang-tidy")
|
||||
harvest(llvm/share/clang llvm/share "run-clang-tidy.py")
|
||||
endif()
|
||||
harvest(llvm/include llvm/include "*")
|
||||
harvest(llvm/bin llvm/bin "llvm-config")
|
||||
harvest(llvm/lib llvm/lib "libLLVM*.a")
|
||||
harvest(llvm/lib llvm/lib "libclang*.a")
|
||||
harvest(llvm/lib/clang llvm/lib/clang "*.h")
|
||||
if(APPLE)
|
||||
harvest(openmp/lib openmp/lib "*")
|
||||
harvest(openmp/include openmp/include "*.h")
|
||||
endif()
|
||||
if(BLENDER_PLATFORM_ARM)
|
||||
harvest(sse2neon sse2neon "*.h")
|
||||
endif()
|
||||
harvest(ogg/lib ffmpeg/lib "*.a")
|
||||
harvest(openal/include openal/include "*.h")
|
||||
if(UNIX AND NOT APPLE)
|
||||
harvest(openal/lib openal/lib "*.a")
|
||||
|
||||
harvest(blosc/include blosc/include "*.h")
|
||||
harvest(blosc/lib blosc/lib "*.a")
|
||||
|
||||
harvest(zlib/include zlib/include "*.h")
|
||||
harvest(zlib/lib zlib/lib "*.a")
|
||||
|
||||
harvest(xml2/include xml2/include "*.h")
|
||||
harvest(xml2/lib xml2/lib "*.a")
|
||||
|
||||
harvest(wayland-protocols/share/wayland-protocols wayland-protocols/share/wayland-protocols/ "*.xml")
|
||||
else()
|
||||
harvest(blosc/lib openvdb/lib "*.a")
|
||||
harvest(xml2/lib opencollada/lib "*.a")
|
||||
endif()
|
||||
harvest(opencollada/include/opencollada opencollada/include "*.h")
|
||||
harvest(opencollada/lib/opencollada opencollada/lib "*.a")
|
||||
harvest(opencolorio/include opencolorio/include "*.h")
|
||||
harvest(opencolorio/lib opencolorio/lib "*.a")
|
||||
harvest(opencolorio/lib/static opencolorio/lib "*.a")
|
||||
harvest(openexr/include openexr/include "*.h")
|
||||
harvest(openexr/lib openexr/lib "*.a")
|
||||
harvest(openimageio/bin openimageio/bin "idiff")
|
||||
harvest(openimageio/bin openimageio/bin "maketx")
|
||||
harvest(openimageio/bin openimageio/bin "oiiotool")
|
||||
harvest(openimageio/include openimageio/include "*")
|
||||
harvest(openimageio/lib openimageio/lib "*.a")
|
||||
harvest(openimagedenoise/include openimagedenoise/include "*")
|
||||
harvest(openimagedenoise/lib openimagedenoise/lib "*.a")
|
||||
harvest(embree/include embree/include "*.h")
|
||||
harvest(embree/lib embree/lib "*.a")
|
||||
harvest(openjpeg/include/openjpeg-${OPENJPEG_SHORT_VERSION} openjpeg/include "*.h")
|
||||
harvest(openjpeg/lib openjpeg/lib "*.a")
|
||||
harvest(opensubdiv/include opensubdiv/include "*.h")
|
||||
harvest(opensubdiv/lib opensubdiv/lib "*.a")
|
||||
harvest(openvdb/include/openvdb openvdb/include/openvdb "*.h")
|
||||
harvest(openvdb/include/nanovdb openvdb/include/nanovdb "*.h")
|
||||
harvest(openvdb/lib openvdb/lib "*.a")
|
||||
harvest(xr_openxr_sdk/include/openxr xr_openxr_sdk/include/openxr "*.h")
|
||||
harvest(xr_openxr_sdk/lib xr_openxr_sdk/lib "*.a")
|
||||
harvest(osl/bin osl/bin "oslc")
|
||||
harvest(osl/include osl/include "*.h")
|
||||
harvest(osl/lib osl/lib "*.a")
|
||||
harvest(osl/share/OSL/shaders osl/share/OSL/shaders "*.h")
|
||||
harvest(png/include png/include "*.h")
|
||||
harvest(png/lib png/lib "*.a")
|
||||
harvest(pugixml/include pugixml/include "*.hpp")
|
||||
harvest(pugixml/lib pugixml/lib "*.a")
|
||||
harvest(python/bin python/bin "python${PYTHON_SHORT_VERSION}")
|
||||
harvest(python/include python/include "*h")
|
||||
harvest(python/lib python/lib "*")
|
||||
harvest(sdl/include/SDL2 sdl/include "*.h")
|
||||
harvest(sdl/lib sdl/lib "libSDL2.a")
|
||||
harvest(sndfile/include sndfile/include "*.h")
|
||||
harvest(sndfile/lib sndfile/lib "*.a")
|
||||
harvest(spnav/include spnav/include "*.h")
|
||||
harvest(spnav/lib spnav/lib "*.a")
|
||||
harvest(tbb/include tbb/include "*.h")
|
||||
harvest(tbb/lib/libtbb_static.a tbb/lib/libtbb.a)
|
||||
harvest(theora/lib ffmpeg/lib "*.a")
|
||||
harvest(tiff/include tiff/include "*.h")
|
||||
harvest(tiff/lib tiff/lib "*.a")
|
||||
harvest(vorbis/lib ffmpeg/lib "*.a")
|
||||
harvest(opus/lib ffmpeg/lib "*.a")
|
||||
harvest(vpx/lib ffmpeg/lib "*.a")
|
||||
harvest(x264/lib ffmpeg/lib "*.a")
|
||||
harvest(xvidcore/lib ffmpeg/lib "*.a")
|
||||
harvest(aom/lib ffmpeg/lib "*.a")
|
||||
harvest(webp/lib webp/lib "*.a")
|
||||
harvest(webp/include webp/include "*.h")
|
||||
harvest(usd/include usd/include "*.h")
|
||||
harvest(usd/lib/usd usd/lib/usd "*")
|
||||
harvest(usd/plugin usd/plugin "*")
|
||||
harvest(potrace/include potrace/include "*.h")
|
||||
harvest(potrace/lib potrace/lib "*.a")
|
||||
harvest(haru/include haru/include "*.h")
|
||||
harvest(haru/lib haru/lib "*.a")
|
||||
harvest(zstd/include zstd/include "*.h")
|
||||
harvest(zstd/lib zstd/lib "*.a")
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
harvest(libglu/lib mesa/lib "*.so*")
|
||||
harvest(mesa/lib64 mesa/lib "*.so*")
|
||||
function(harvest from to)
|
||||
set(pattern "")
|
||||
foreach(f ${ARGN})
|
||||
set(pattern ${f})
|
||||
endforeach()
|
||||
|
||||
harvest(dpcpp dpcpp "*")
|
||||
harvest(igc dpcpp/lib/igc "*")
|
||||
harvest(ocloc dpcpp/lib/ocloc "*")
|
||||
endif()
|
||||
if(pattern STREQUAL "")
|
||||
get_filename_component(dirpath ${to} DIRECTORY)
|
||||
get_filename_component(filename ${to} NAME)
|
||||
install(
|
||||
FILES ${LIBDIR}/${from}
|
||||
DESTINATION ${HARVEST_TARGET}/${dirpath}
|
||||
RENAME ${filename}
|
||||
)
|
||||
else()
|
||||
install(
|
||||
DIRECTORY ${LIBDIR}/${from}/
|
||||
DESTINATION ${HARVEST_TARGET}/${to}
|
||||
USE_SOURCE_PERMISSIONS
|
||||
FILES_MATCHING PATTERN ${pattern}
|
||||
PATTERN "pkgconfig" EXCLUDE
|
||||
PATTERN "cmake" EXCLUDE
|
||||
PATTERN "__pycache__" EXCLUDE
|
||||
PATTERN "tests" EXCLUDE
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
harvest(alembic/include alembic/include "*.h")
|
||||
harvest(alembic/lib/libAlembic.a alembic/lib/libAlembic.a)
|
||||
harvest(alembic/bin alembic/bin "*")
|
||||
harvest(brotli/include brotli/include "*.h")
|
||||
harvest(brotli/lib brotli/lib "*.a")
|
||||
harvest(boost/include boost/include "*")
|
||||
harvest(boost/lib boost/lib "*.a")
|
||||
harvest(imath/include imath/include "*.h")
|
||||
harvest(imath/lib imath/lib "*.a")
|
||||
harvest(ffmpeg/include ffmpeg/include "*.h")
|
||||
harvest(ffmpeg/lib ffmpeg/lib "*.a")
|
||||
harvest(fftw3/include fftw3/include "*.h")
|
||||
harvest(fftw3/lib fftw3/lib "*.a")
|
||||
harvest(flac/lib sndfile/lib "libFLAC.a")
|
||||
harvest(freetype/include freetype/include "*.h")
|
||||
harvest(freetype/lib/libfreetype2ST.a freetype/lib/libfreetype.a)
|
||||
harvest(epoxy/include epoxy/include "*.h")
|
||||
harvest(epoxy/lib epoxy/lib "*.a")
|
||||
harvest(gmp/include gmp/include "*.h")
|
||||
harvest(gmp/lib gmp/lib "*.a")
|
||||
harvest(jemalloc/include jemalloc/include "*.h")
|
||||
harvest(jemalloc/lib jemalloc/lib "*.a")
|
||||
harvest(jpeg/include jpeg/include "*.h")
|
||||
harvest(jpeg/lib jpeg/lib "libjpeg.a")
|
||||
harvest(lame/lib ffmpeg/lib "*.a")
|
||||
if(NOT APPLE)
|
||||
harvest(level-zero/include/level_zero level-zero/include/level_zero "*.h")
|
||||
harvest(level-zero/lib level-zero/lib "*.so*")
|
||||
endif()
|
||||
harvest(llvm/bin llvm/bin "clang-format")
|
||||
if(BUILD_CLANG_TOOLS)
|
||||
harvest(llvm/bin llvm/bin "clang-tidy")
|
||||
harvest(llvm/share/clang llvm/share "run-clang-tidy.py")
|
||||
endif()
|
||||
harvest(llvm/include llvm/include "*")
|
||||
harvest(llvm/bin llvm/bin "llvm-config")
|
||||
harvest(llvm/lib llvm/lib "libLLVM*.a")
|
||||
harvest(llvm/lib llvm/lib "libclang*.a")
|
||||
harvest(llvm/lib/clang llvm/lib/clang "*.h")
|
||||
if(APPLE)
|
||||
harvest(openmp/lib openmp/lib "*")
|
||||
harvest(openmp/include openmp/include "*.h")
|
||||
endif()
|
||||
if(BLENDER_PLATFORM_ARM)
|
||||
harvest(sse2neon sse2neon "*.h")
|
||||
endif()
|
||||
harvest(ogg/lib ffmpeg/lib "*.a")
|
||||
harvest(openal/include openal/include "*.h")
|
||||
if(UNIX AND NOT APPLE)
|
||||
harvest(openal/lib openal/lib "*.a")
|
||||
|
||||
harvest(blosc/include blosc/include "*.h")
|
||||
harvest(blosc/lib blosc/lib "*.a")
|
||||
|
||||
harvest(zlib/include zlib/include "*.h")
|
||||
harvest(zlib/lib zlib/lib "*.a")
|
||||
|
||||
harvest(xml2/include xml2/include "*.h")
|
||||
harvest(xml2/lib xml2/lib "*.a")
|
||||
|
||||
harvest(wayland-protocols/share/wayland-protocols wayland-protocols/share/wayland-protocols/ "*.xml")
|
||||
harvest(wayland/bin wayland/bin "wayland-scanner")
|
||||
else()
|
||||
harvest(blosc/lib openvdb/lib "*.a")
|
||||
harvest(xml2/lib opencollada/lib "*.a")
|
||||
endif()
|
||||
harvest(opencollada/include/opencollada opencollada/include "*.h")
|
||||
harvest(opencollada/lib/opencollada opencollada/lib "*.a")
|
||||
harvest(opencolorio/include opencolorio/include "*.h")
|
||||
harvest(opencolorio/lib opencolorio/lib "*.a")
|
||||
harvest(opencolorio/lib/static opencolorio/lib "*.a")
|
||||
harvest(openexr/include openexr/include "*.h")
|
||||
harvest(openexr/lib openexr/lib "*.a")
|
||||
harvest(openimageio/bin openimageio/bin "idiff")
|
||||
harvest(openimageio/bin openimageio/bin "maketx")
|
||||
harvest(openimageio/bin openimageio/bin "oiiotool")
|
||||
harvest(openimageio/include openimageio/include "*")
|
||||
harvest(openimageio/lib openimageio/lib "*.a")
|
||||
harvest(openimagedenoise/include openimagedenoise/include "*")
|
||||
harvest(openimagedenoise/lib openimagedenoise/lib "*.a")
|
||||
harvest(embree/include embree/include "*.h")
|
||||
harvest(embree/lib embree/lib "*.a")
|
||||
harvest(openpgl/include openpgl/include "*.h")
|
||||
harvest(openpgl/lib openpgl/lib "*.a")
|
||||
harvest(openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION} openpgl/lib/cmake/openpgl "*.cmake")
|
||||
harvest(openjpeg/include/openjpeg-${OPENJPEG_SHORT_VERSION} openjpeg/include "*.h")
|
||||
harvest(openjpeg/lib openjpeg/lib "*.a")
|
||||
harvest(opensubdiv/include opensubdiv/include "*.h")
|
||||
harvest(opensubdiv/lib opensubdiv/lib "*.a")
|
||||
harvest(openvdb/include/openvdb openvdb/include/openvdb "*.h")
|
||||
harvest(openvdb/include/nanovdb openvdb/include/nanovdb "*.h")
|
||||
harvest(openvdb/lib openvdb/lib "*.a")
|
||||
harvest(xr_openxr_sdk/include/openxr xr_openxr_sdk/include/openxr "*.h")
|
||||
harvest(xr_openxr_sdk/lib xr_openxr_sdk/lib "*.a")
|
||||
harvest(osl/bin osl/bin "oslc")
|
||||
harvest(osl/include osl/include "*.h")
|
||||
harvest(osl/lib osl/lib "*.a")
|
||||
harvest(osl/share/OSL/shaders osl/share/OSL/shaders "*.h")
|
||||
harvest(png/include png/include "*.h")
|
||||
harvest(png/lib png/lib "*.a")
|
||||
harvest(pugixml/include pugixml/include "*.hpp")
|
||||
harvest(pugixml/lib pugixml/lib "*.a")
|
||||
harvest(python/bin python/bin "python${PYTHON_SHORT_VERSION}")
|
||||
harvest(python/include python/include "*h")
|
||||
harvest(python/lib python/lib "*")
|
||||
harvest(sdl/include/SDL2 sdl/include "*.h")
|
||||
harvest(sdl/lib sdl/lib "libSDL2.a")
|
||||
harvest(sndfile/include sndfile/include "*.h")
|
||||
harvest(sndfile/lib sndfile/lib "*.a")
|
||||
harvest(spnav/include spnav/include "*.h")
|
||||
harvest(spnav/lib spnav/lib "*.a")
|
||||
harvest(tbb/include tbb/include "*.h")
|
||||
harvest(tbb/lib/libtbb_static.a tbb/lib/libtbb.a)
|
||||
harvest(theora/lib ffmpeg/lib "*.a")
|
||||
harvest(tiff/include tiff/include "*.h")
|
||||
harvest(tiff/lib tiff/lib "*.a")
|
||||
harvest(vorbis/lib ffmpeg/lib "*.a")
|
||||
harvest(opus/lib ffmpeg/lib "*.a")
|
||||
harvest(vpx/lib ffmpeg/lib "*.a")
|
||||
harvest(x264/lib ffmpeg/lib "*.a")
|
||||
harvest(xvidcore/lib ffmpeg/lib "*.a")
|
||||
harvest(aom/lib ffmpeg/lib "*.a")
|
||||
harvest(webp/lib webp/lib "*.a")
|
||||
harvest(webp/include webp/include "*.h")
|
||||
harvest(usd/include usd/include "*.h")
|
||||
harvest(usd/lib/usd usd/lib/usd "*")
|
||||
harvest(usd/plugin usd/plugin "*")
|
||||
harvest(potrace/include potrace/include "*.h")
|
||||
harvest(potrace/lib potrace/lib "*.a")
|
||||
harvest(haru/include haru/include "*.h")
|
||||
harvest(haru/lib haru/lib "*.a")
|
||||
harvest(zstd/include zstd/include "*.h")
|
||||
harvest(zstd/lib zstd/lib "*.a")
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
harvest(libglu/lib mesa/lib "*.so*")
|
||||
harvest(mesa/lib64 mesa/lib "*.so*")
|
||||
|
||||
harvest(dpcpp dpcpp "*")
|
||||
harvest(igc dpcpp/lib/igc "*")
|
||||
harvest(ocloc dpcpp/lib/ocloc "*")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
if(WIN32)
|
||||
# cmake for windows
|
||||
# CMAKE for MS-Windows.
|
||||
set(JPEG_EXTRA_ARGS
|
||||
-DNASM=${NASM_PATH}
|
||||
-DWITH_JPEG8=ON
|
||||
@@ -33,8 +33,8 @@ if(WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
else(WIN32)
|
||||
# cmake for unix
|
||||
else()
|
||||
# CMAKE for UNIX.
|
||||
set(JPEG_EXTRA_ARGS
|
||||
-DWITH_JPEG8=ON
|
||||
-DENABLE_STATIC=ON
|
||||
|
49
build_files/build_environment/cmake/openpgl.cmake
Normal file
49
build_files/build_environment/cmake/openpgl.cmake
Normal file
@@ -0,0 +1,49 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# Note the utility apps may use png/tiff/gif system libraries, but the
|
||||
# library itself does not depend on them, so should give no problems.
|
||||
|
||||
set(OPENPGL_EXTRA_ARGS
|
||||
-DOPENPGL_BUILD_PYTHON=OFF
|
||||
-DOPENPGL_BUILD_STATIC=ON
|
||||
-DOPENPGL_TBB_ROOT=${LIBDIR}/tbb
|
||||
-DTBB_ROOT=${LIBDIR}/tbb
|
||||
-Dembree_DIR=${LIBDIR}/embree/lib/cmake/embree-${EMBREE_VERSION}
|
||||
-DCMAKE_DEBUG_POSTFIX=_d
|
||||
)
|
||||
|
||||
if(TBB_STATIC_LIBRARY)
|
||||
set(OPENPGL_EXTRA_ARGS
|
||||
${OPENPGL_EXTRA_ARGS}
|
||||
-DOPENPGL_TBB_COMPONENT=tbb_static
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_openpgl
|
||||
URL file://${PACKAGE_DIR}/${OPENPGL_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${OPENPGL_HASH_TYPE}=${OPENPGL_HASH}
|
||||
PREFIX ${BUILD_DIR}/openpgl
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openpgl ${DEFAULT_CMAKE_FLAGS} ${OPENPGL_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/openpgl
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_openpgl
|
||||
external_tbb
|
||||
external_embree
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_openpgl after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openpgl ${HARVEST_TARGET}/openpgl
|
||||
DEPENDEES install
|
||||
)
|
||||
else()
|
||||
ExternalProject_Add_Step(external_openpgl after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openpgl/lib/openpgl_d.lib ${HARVEST_TARGET}/openpgl/lib/openpgl_d.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
endif()
|
@@ -15,7 +15,7 @@ message("BuildMode = ${BUILD_MODE}")
|
||||
|
||||
if(BUILD_MODE STREQUAL "Debug")
|
||||
set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Debug)
|
||||
else(BUILD_MODE STREQUAL "Debug")
|
||||
else()
|
||||
set(LIBDIR ${CMAKE_CURRENT_BINARY_DIR}/Release)
|
||||
endif()
|
||||
|
||||
|
@@ -458,6 +458,12 @@ set(WL_PROTOCOLS_URI https://gitlab.freedesktop.org/wayland/wayland-protocols/-/
|
||||
set(WL_PROTOCOLS_HASH af5ca07e13517cdbab33504492cef54a)
|
||||
set(WL_PROTOCOLS_HASH_TYPE MD5)
|
||||
|
||||
set(WAYLAND_VERSION 1.21.0)
|
||||
set(WAYLAND_FILE wayland-${WAYLAND_VERSION}.tar.xz)
|
||||
set(WAYLAND_URI https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.21.0/downloads/wayland-${WAYLAND_VERSION}.tar.xz)
|
||||
set(WAYLAND_HASH f2653a2293bcd882d756c6a83d278903)
|
||||
set(WAYLAND_HASH_TYPE MD5)
|
||||
|
||||
set(ISPC_VERSION v1.17.0)
|
||||
set(ISPC_URI https://github.com/ispc/ispc/archive/${ISPC_VERSION}.tar.gz)
|
||||
set(ISPC_HASH 4f476a3109332a77fe839a9014c60ca9)
|
||||
@@ -500,6 +506,13 @@ set(BROTLI_HASH f9e8d81d0405ba66d181529af42a3354f838c939095ff99930da6aa9cdf6fe46
|
||||
set(BROTLI_HASH_TYPE SHA256)
|
||||
set(BROTLI_FILE brotli-${BROTLI_VERSION}.tar.gz)
|
||||
|
||||
set(OPENPGL_VERSION v0.3.1-beta)
|
||||
set(OPENPGL_SHORT_VERSION 0.3.1)
|
||||
set(OPENPGL_URI https://github.com/OpenPathGuidingLibrary/openpgl/archive/refs/tags/${OPENPGL_VERSION}.tar.gz)
|
||||
set(OPENPGL_HASH 3830098c485c962018932766199527aab453a8029528dbbc04d4454d82431e2c)
|
||||
set(OPENPGL_HASH_TYPE SHA256)
|
||||
set(OPENPGL_FILE openpgl-${OPENPGL_VERSION}.tar.gz)
|
||||
|
||||
set(LEVEL_ZERO_VERSION v1.7.15)
|
||||
set(LEVEL_ZERO_URI https://github.com/oneapi-src/level-zero/archive/refs/tags/${LEVEL_ZERO_VERSION}.tar.gz)
|
||||
set(LEVEL_ZERO_HASH c39bb05a8e5898aa6c444e1704105b93d3f1888b9c333f8e7e73825ffbfb2617)
|
||||
|
19
build_files/build_environment/cmake/wayland.cmake
Normal file
19
build_files/build_environment/cmake/wayland.cmake
Normal file
@@ -0,0 +1,19 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
ExternalProject_Add(external_wayland
|
||||
URL file://${PACKAGE_DIR}/${WAYLAND_FILE}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH ${WAYLAND_HASH_TYPE}=${WAYLAND_HASH}
|
||||
PREFIX ${BUILD_DIR}/wayland
|
||||
PATCH_COMMAND ${PATCH_CMD} -d ${BUILD_DIR}/wayland/src/external_wayland < ${PATCH_DIR}/wayland.diff
|
||||
# Use `-E` so the `PKG_CONFIG_PATH` can be defined to link against our own LIBEXPAT.
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env PKG_CONFIG_PATH=${LIBDIR}/expat/lib/pkgconfig
|
||||
meson --prefix ${LIBDIR}/wayland -Ddocumentation=false -Dtests=false -Dlibraries=false . ../external_wayland
|
||||
BUILD_COMMAND ninja
|
||||
INSTALL_COMMAND ninja install
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
external_wayland
|
||||
external_expat
|
||||
)
|
@@ -14,3 +14,15 @@ index 7b894a45..92618215 100644
|
||||
)
|
||||
if(CMAKE_TOOLCHAIN_FILE)
|
||||
set(pystring_CMAKE_ARGS
|
||||
--- a/src/OpenColorIO/FileRules.cpp
|
||||
+++ b/src/OpenColorIO/FileRules.cpp
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
+/* NOTE: this has been applied up-stream, this edit can be removed after upgrading OpenColorIO. */
|
||||
+#include <cstring>
|
||||
+
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
|
||||
#include "CustomKeys.h"
|
||||
|
11
build_files/build_environment/patches/wayland.diff
Normal file
11
build_files/build_environment/patches/wayland.diff
Normal file
@@ -0,0 +1,11 @@
|
||||
--- meson.build.orig 2022-06-30 22:59:11.000000000 +0100
|
||||
+++ meson.build 2022-09-27 13:21:26.428517668 +0100
|
||||
@@ -2,7 +2,7 @@
|
||||
'wayland', 'c',
|
||||
version: '1.21.0',
|
||||
license: 'MIT',
|
||||
- meson_version: '>= 0.56.0',
|
||||
+ meson_version: '>= 0.55.1',
|
||||
default_options: [
|
||||
'warning_level=2',
|
||||
'buildtype=debugoptimized',
|
@@ -44,7 +44,7 @@ FIND_PROGRAM(SYCL_COMPILER
|
||||
# compiler.
|
||||
if(NOT SYCL_COMPILER)
|
||||
FIND_PROGRAM(SYCL_COMPILER
|
||||
NAMES
|
||||
NAMES
|
||||
dpcpp
|
||||
HINTS
|
||||
${_sycl_search_dirs}
|
||||
|
@@ -40,12 +40,10 @@ macro(BLENDER_SRC_GTEST_EX)
|
||||
set(MANIFEST "${CMAKE_BINARY_DIR}/tests.exe.manifest")
|
||||
endif()
|
||||
|
||||
add_definitions(-DBLENDER_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
|
||||
add_definitions(${GFLAGS_DEFINES})
|
||||
add_definitions(${GLOG_DEFINES})
|
||||
|
||||
add_executable(${TARGET_NAME} ${ARG_SRC} ${MANIFEST})
|
||||
setup_platform_linker_flags(${TARGET_NAME})
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE ${GFLAGS_DEFINES})
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE ${GLOG_DEFINES})
|
||||
target_include_directories(${TARGET_NAME} PUBLIC "${TEST_INC}")
|
||||
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC "${TEST_INC_SYS}")
|
||||
target_link_libraries(${TARGET_NAME} ${ARG_EXTRA_LIBS} ${PLATFORM_LINKLIBS})
|
||||
|
@@ -150,10 +150,10 @@ endif()
|
||||
# BUILD_PLATFORM is taken from CMake
|
||||
# but BUILD_DATE and BUILD_TIME are platform dependent
|
||||
if(NOT BUILD_DATE)
|
||||
STRING(TIMESTAMP BUILD_DATE "%Y-%m-%d" UTC)
|
||||
string(TIMESTAMP BUILD_DATE "%Y-%m-%d" UTC)
|
||||
endif()
|
||||
if(NOT BUILD_TIME)
|
||||
STRING(TIMESTAMP BUILD_TIME "%H:%M:%S" UTC)
|
||||
string(TIMESTAMP BUILD_TIME "%H:%M:%S" UTC)
|
||||
endif()
|
||||
|
||||
# Write a file with the BUILD_HASH define
|
||||
|
@@ -17,6 +17,7 @@ set(WITH_COMPOSITOR_CPU ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_PATH_GUIDING ON CACHE BOOL "" FORCE)
|
||||
set(WITH_DRACO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
|
||||
|
@@ -18,6 +18,7 @@ set(WITH_COMPOSITOR_CPU ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_EMBREE ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_OSL ON CACHE BOOL "" FORCE)
|
||||
set(WITH_CYCLES_PATH_GUIDING ON CACHE BOOL "" FORCE)
|
||||
set(WITH_DRACO ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FFTW3 ON CACHE BOOL "" FORCE)
|
||||
set(WITH_FREESTYLE ON CACHE BOOL "" FORCE)
|
||||
|
@@ -134,12 +134,11 @@ endfunction()
|
||||
|
||||
# Nicer makefiles with -I/1/foo/ instead of -I/1/2/3/../../foo/
|
||||
# use it instead of include_directories()
|
||||
function(blender_include_dirs
|
||||
includes
|
||||
)
|
||||
function(absolute_include_dirs
|
||||
includes_absolute)
|
||||
|
||||
set(_ALL_INCS "")
|
||||
foreach(_INC ${ARGV})
|
||||
foreach(_INC ${ARGN})
|
||||
get_filename_component(_ABS_INC ${_INC} ABSOLUTE)
|
||||
list(APPEND _ALL_INCS ${_ABS_INC})
|
||||
# for checking for invalid includes, disable for regular use
|
||||
@@ -147,22 +146,24 @@ function(blender_include_dirs
|
||||
# message(FATAL_ERROR "Include not found: ${_ABS_INC}/")
|
||||
# endif()
|
||||
endforeach()
|
||||
include_directories(${_ALL_INCS})
|
||||
|
||||
set(${includes_absolute} ${_ALL_INCS} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(blender_include_dirs_sys
|
||||
includes
|
||||
function(blender_target_include_dirs
|
||||
name
|
||||
)
|
||||
|
||||
set(_ALL_INCS "")
|
||||
foreach(_INC ${ARGV})
|
||||
get_filename_component(_ABS_INC ${_INC} ABSOLUTE)
|
||||
list(APPEND _ALL_INCS ${_ABS_INC})
|
||||
# if(NOT EXISTS "${_ABS_INC}/")
|
||||
# message(FATAL_ERROR "Include not found: ${_ABS_INC}/")
|
||||
# endif()
|
||||
endforeach()
|
||||
include_directories(SYSTEM ${_ALL_INCS})
|
||||
absolute_include_dirs(_ALL_INCS ${ARGN})
|
||||
target_include_directories(${name} PRIVATE ${_ALL_INCS})
|
||||
endfunction()
|
||||
|
||||
function(blender_target_include_dirs_sys
|
||||
name
|
||||
)
|
||||
|
||||
absolute_include_dirs(_ALL_INCS ${ARGN})
|
||||
target_include_directories(${name} SYSTEM PRIVATE ${_ALL_INCS})
|
||||
endfunction()
|
||||
|
||||
# Set include paths for header files included with "*.h" syntax.
|
||||
@@ -268,13 +269,11 @@ function(blender_add_lib__impl
|
||||
|
||||
# message(STATUS "Configuring library ${name}")
|
||||
|
||||
# include_directories(${includes})
|
||||
# include_directories(SYSTEM ${includes_sys})
|
||||
blender_include_dirs("${includes}")
|
||||
blender_include_dirs_sys("${includes_sys}")
|
||||
|
||||
add_library(${name} ${sources})
|
||||
|
||||
blender_target_include_dirs(${name} ${includes})
|
||||
blender_target_include_dirs_sys(${name} ${includes_sys})
|
||||
|
||||
# On Windows certain libraries have two sets of binaries: one for debug builds and one for
|
||||
# release builds. The root of this requirement goes into ABI, I believe, but that's outside
|
||||
# of a scope of this comment.
|
||||
@@ -382,7 +381,7 @@ function(blender_add_test_suite)
|
||||
cmake_parse_arguments(ARGS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
# Figure out the release dir, as some tests need files from there.
|
||||
GET_BLENDER_TEST_INSTALL_DIR(TEST_INSTALL_DIR)
|
||||
get_blender_test_install_dir(TEST_INSTALL_DIR)
|
||||
if(APPLE)
|
||||
set(_test_release_dir ${TEST_INSTALL_DIR}/Blender.app/Contents/Resources/${BLENDER_VERSION})
|
||||
else()
|
||||
@@ -418,13 +417,6 @@ function(blender_add_test_lib
|
||||
library_deps
|
||||
)
|
||||
|
||||
# Not currently supported for Python module due to different required
|
||||
# Python link flags.
|
||||
if(WITH_PYTHON_MODULE)
|
||||
add_custom_target(${name})
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_cc_flags_custom_test(${name} PARENT_SCOPE)
|
||||
|
||||
# Otherwise external projects will produce warnings that we cannot fix.
|
||||
@@ -432,21 +424,21 @@ function(blender_add_test_lib
|
||||
|
||||
# This duplicates logic that's also in GTestTesting.cmake, macro BLENDER_SRC_GTEST_EX.
|
||||
# TODO(Sybren): deduplicate after the general approach in D7649 has been approved.
|
||||
LIST(APPEND includes
|
||||
list(APPEND includes
|
||||
${CMAKE_SOURCE_DIR}/tests/gtests
|
||||
)
|
||||
LIST(APPEND includes_sys
|
||||
list(APPEND includes_sys
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFLAGS_INCLUDE_DIRS}
|
||||
${CMAKE_SOURCE_DIR}/extern/gtest/include
|
||||
${CMAKE_SOURCE_DIR}/extern/gmock/include
|
||||
)
|
||||
add_definitions(-DBLENDER_GFLAGS_NAMESPACE=${GFLAGS_NAMESPACE})
|
||||
add_definitions(${GFLAGS_DEFINES})
|
||||
add_definitions(${GLOG_DEFINES})
|
||||
|
||||
blender_add_lib__impl(${name} "${sources}" "${includes}" "${includes_sys}" "${library_deps}")
|
||||
|
||||
target_compile_definitions(${name} PRIVATE ${GFLAGS_DEFINES})
|
||||
target_compile_definitions(${name} PRIVATE ${GLOG_DEFINES})
|
||||
|
||||
set_property(GLOBAL APPEND PROPERTY BLENDER_TEST_LIBS ${name})
|
||||
|
||||
blender_add_test_suite(
|
||||
@@ -471,28 +463,21 @@ function(blender_add_test_executable
|
||||
library_deps
|
||||
)
|
||||
|
||||
# Not currently supported for Python module due to different required
|
||||
# Python link flags.
|
||||
if(WITH_PYTHON_MODULE)
|
||||
add_custom_target(${name})
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_cc_flags_custom_test(${name} PARENT_SCOPE)
|
||||
|
||||
## Otherwise external projects will produce warnings that we cannot fix.
|
||||
remove_strict_flags()
|
||||
|
||||
include_directories(${includes})
|
||||
include_directories(${includes_sys})
|
||||
|
||||
BLENDER_SRC_GTEST_EX(
|
||||
blender_src_gtest_ex(
|
||||
NAME ${name}
|
||||
SRC "${sources}"
|
||||
EXTRA_LIBS "${library_deps}"
|
||||
SKIP_ADD_TEST
|
||||
)
|
||||
|
||||
blender_target_include_dirs(${name}_test ${includes})
|
||||
blender_target_include_dirs_sys(${name}_test ${includes_sys})
|
||||
|
||||
blender_add_test_suite(
|
||||
TARGET ${name}_test
|
||||
SUITE_NAME ${name}
|
||||
@@ -527,6 +512,11 @@ function(setup_platform_linker_flags
|
||||
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${PLATFORM_LINKFLAGS}")
|
||||
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_RELEASE " ${PLATFORM_LINKFLAGS_RELEASE}")
|
||||
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS_DEBUG " ${PLATFORM_LINKFLAGS_DEBUG}")
|
||||
|
||||
get_target_property(target_type ${target} TYPE)
|
||||
if (target_type STREQUAL "EXECUTABLE")
|
||||
set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${PLATFORM_LINKFLAGS_EXECUTABLE}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Platform specific libraries for targets.
|
||||
@@ -774,7 +764,7 @@ function(ADD_CHECK_C_COMPILER_FLAG
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
|
||||
CHECK_C_COMPILER_FLAG("${_FLAG}" "${_CACHE_VAR}")
|
||||
check_c_compiler_flag("${_FLAG}" "${_CACHE_VAR}")
|
||||
if(${_CACHE_VAR})
|
||||
# message(STATUS "Using CFLAG: ${_FLAG}")
|
||||
set(${_CFLAGS} "${${_CFLAGS}} ${_FLAG}" PARENT_SCOPE)
|
||||
@@ -791,7 +781,7 @@ function(ADD_CHECK_CXX_COMPILER_FLAG
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
CHECK_CXX_COMPILER_FLAG("${_FLAG}" "${_CACHE_VAR}")
|
||||
check_cxx_compiler_flag("${_FLAG}" "${_CACHE_VAR}")
|
||||
if(${_CACHE_VAR})
|
||||
# message(STATUS "Using CXXFLAG: ${_FLAG}")
|
||||
set(${_CXXFLAGS} "${${_CXXFLAGS}} ${_FLAG}" PARENT_SCOPE)
|
||||
@@ -809,9 +799,11 @@ function(get_blender_version)
|
||||
# - BLENDER_VERSION_PATCH
|
||||
# - BLENDER_VERSION_CYCLE (alpha, beta, rc, release)
|
||||
|
||||
# So cmake depends on BKE_blender.h, beware of inf-loops!
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/source/blender/blenkernel/BKE_blender_version.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/blenkernel/BKE_blender_version.h.done)
|
||||
# So CMAKE depends on `BKE_blender.h`, beware of infinite-loops!
|
||||
configure_file(
|
||||
${CMAKE_SOURCE_DIR}/source/blender/blenkernel/BKE_blender_version.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/blenkernel/BKE_blender_version.h.done
|
||||
)
|
||||
|
||||
file(STRINGS ${CMAKE_SOURCE_DIR}/source/blender/blenkernel/BKE_blender_version.h _contents REGEX "^#define[ \t]+BLENDER_.*$")
|
||||
|
||||
@@ -1198,8 +1190,6 @@ macro(openmp_delayload
|
||||
if(WITH_OPENMP)
|
||||
if(MSVC_CLANG)
|
||||
set(OPENMP_DLL_NAME "libomp")
|
||||
elseif(MSVC_VERSION EQUAL 1800)
|
||||
set(OPENMP_DLL_NAME "vcomp120")
|
||||
else()
|
||||
set(OPENMP_DLL_NAME "vcomp140")
|
||||
endif()
|
||||
|
@@ -17,9 +17,9 @@ set(CPACK_PACKAGE_VENDOR ${PROJECT_VENDOR})
|
||||
set(CPACK_PACKAGE_CONTACT ${PROJECT_CONTACT})
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR "${MAJOR_VERSION}")
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR "${MINOR_VERSION}")
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH "${PATCH_VERSION}")
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "${MAJOR_VERSION}")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "${MINOR_VERSION}")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "${PATCH_VERSION}")
|
||||
|
||||
|
||||
# Get the build revision, note that this can get out-of-sync, so for packaging run cmake first.
|
||||
@@ -48,7 +48,7 @@ if(MSVC)
|
||||
else()
|
||||
set(PACKAGE_ARCH windows32)
|
||||
endif()
|
||||
else(MSVC)
|
||||
else()
|
||||
set(PACKAGE_ARCH ${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
|
||||
|
@@ -30,16 +30,12 @@ macro(add_bundled_libraries library)
|
||||
list(APPEND PLATFORM_BUNDLED_LIBRARY_DIRS ${_library_dir})
|
||||
unset(_all_library_versions)
|
||||
unset(_library_dir)
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# ------------------------------------------------------------------------
|
||||
# Find system provided libraries.
|
||||
|
||||
# Avoid searching for headers since this would otherwise override our lib
|
||||
# directory as well as PYTHON_ROOT_DIR.
|
||||
set(CMAKE_FIND_FRAMEWORK NEVER)
|
||||
|
||||
# Find system ZLIB, not the pre-compiled one supplied with OpenCollada.
|
||||
set(ZLIB_ROOT /usr)
|
||||
find_package(ZLIB REQUIRED)
|
||||
@@ -79,6 +75,10 @@ if(NOT EXISTS "${LIBDIR}/")
|
||||
message(FATAL_ERROR "Mac OSX requires pre-compiled libs at: '${LIBDIR}'")
|
||||
endif()
|
||||
|
||||
# Avoid searching for headers since this would otherwise override our lib
|
||||
# directory as well as PYTHON_ROOT_DIR.
|
||||
set(CMAKE_FIND_FRAMEWORK NEVER)
|
||||
|
||||
# Optionally use system Python if PYTHON_ROOT_DIR is specified.
|
||||
if(WITH_PYTHON AND (WITH_PYTHON_MODULE AND PYTHON_ROOT_DIR))
|
||||
find_package(PythonLibsUnix REQUIRED)
|
||||
@@ -324,7 +324,7 @@ if(WITH_LLVM)
|
||||
if(WITH_CLANG)
|
||||
find_package(Clang)
|
||||
if(NOT CLANG_FOUND)
|
||||
message(FATAL_ERROR "Clang not found.")
|
||||
message(FATAL_ERROR "Clang not found.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -352,10 +352,6 @@ endif()
|
||||
|
||||
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
||||
find_package(Embree 3.8.0 REQUIRED)
|
||||
# Increase stack size for Embree, only works for executables.
|
||||
if(NOT WITH_PYTHON_MODULE)
|
||||
string(APPEND PLATFORM_LINKFLAGS " -Wl,-stack_size,0x100000")
|
||||
endif()
|
||||
|
||||
# Embree static library linking can mix up SSE and AVX symbols, causing
|
||||
# crashes on macOS systems with older CPUs that don't have AVX. Using
|
||||
@@ -475,6 +471,9 @@ string(APPEND PLATFORM_LINKFLAGS
|
||||
string(APPEND CMAKE_CXX_FLAGS " -stdlib=libc++")
|
||||
string(APPEND PLATFORM_LINKFLAGS " -stdlib=libc++")
|
||||
|
||||
# Make stack size more similar to Embree, required for Embree.
|
||||
string(APPEND PLATFORM_LINKFLAGS_EXECUTABLE " -Wl,-stack_size,0x100000")
|
||||
|
||||
# Suppress ranlib "has no symbols" warnings (workaround for T48250)
|
||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
|
@@ -26,11 +26,6 @@ if(NOT DEFINED LIBDIR)
|
||||
else()
|
||||
set(WITH_LIBC_MALLOC_HOOK_WORKAROUND True)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND
|
||||
CMAKE_C_COMPILER_VERSION VERSION_LESS 9.3)
|
||||
message(FATAL_ERROR "GCC version must be at least 9.3 for precompiled libraries, found ${CMAKE_C_COMPILER_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Avoid namespace pollustion.
|
||||
@@ -94,7 +89,7 @@ macro(add_bundled_libraries library)
|
||||
file(GLOB _all_library_versions ${LIBDIR}/${library}/lib/*\.so*)
|
||||
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_all_library_versions})
|
||||
unset(_all_library_versions)
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
@@ -769,7 +764,44 @@ if(WITH_GHOST_WAYLAND)
|
||||
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
|
||||
endif()
|
||||
|
||||
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
|
||||
if(EXISTS "${LIBDIR}/wayland/bin/wayland-scanner")
|
||||
set(WAYLAND_SCANNER "${LIBDIR}/wayland/bin/wayland-scanner")
|
||||
else()
|
||||
pkg_get_variable(WAYLAND_SCANNER wayland-scanner wayland_scanner)
|
||||
endif()
|
||||
|
||||
# When using dynamic loading, headers generated
|
||||
# from older versions of `wayland-scanner` aren't compatible.
|
||||
if(WITH_GHOST_WAYLAND_DYNLOAD)
|
||||
execute_process(
|
||||
COMMAND ${WAYLAND_SCANNER} --version
|
||||
# The version is written to the `stderr`.
|
||||
ERROR_VARIABLE _wayland_scanner_out
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NOT "${_wayland_scanner_out}" STREQUAL "")
|
||||
string(
|
||||
REGEX REPLACE
|
||||
"^wayland-scanner[ \t]+([0-9]+)\.([0-9]+).*"
|
||||
"\\1.\\2"
|
||||
_wayland_scanner_ver
|
||||
"${_wayland_scanner_out}"
|
||||
)
|
||||
if("${_wayland_scanner_ver}" VERSION_LESS "1.20")
|
||||
message(
|
||||
FATAL_ERROR
|
||||
"Found ${WAYLAND_SCANNER} version \"${_wayland_scanner_ver}\", "
|
||||
"the minimum version is 1.20!"
|
||||
)
|
||||
endif()
|
||||
unset(_wayland_scanner_ver)
|
||||
else()
|
||||
message(WARNING "Unable to access the version from ${WAYLAND_SCANNER}, continuing.")
|
||||
endif()
|
||||
unset(_wayland_scanner_out)
|
||||
endif()
|
||||
# End wayland-scanner version check.
|
||||
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1056,7 +1088,7 @@ function(CONFIGURE_ATOMIC_LIB_IF_NEEDED)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
CONFIGURE_ATOMIC_LIB_IF_NEEDED()
|
||||
configure_atomic_lib_if_needed()
|
||||
|
||||
if(PLATFORM_BUNDLED_LIBRARIES)
|
||||
# For the installed Python module and installed Blender executable, we set the
|
||||
|
@@ -26,7 +26,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(OPENMP_FOUND ON)
|
||||
set(OpenMP_C_FLAGS "/clang:-fopenmp")
|
||||
set(OpenMP_CXX_FLAGS "/clang:-fopenmp")
|
||||
GET_FILENAME_COMPONENT(LLVMROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM;]" ABSOLUTE CACHE)
|
||||
get_filename_component(LLVMROOT "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM;]" ABSOLUTE CACHE)
|
||||
set(CLANG_OPENMP_DLL "${LLVMROOT}/bin/libomp.dll")
|
||||
set(CLANG_OPENMP_LIB "${LLVMROOT}/lib/libomp.lib")
|
||||
if(NOT EXISTS "${CLANG_OPENMP_DLL}")
|
||||
@@ -74,27 +74,6 @@ add_definitions(-DWIN32)
|
||||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
|
||||
# Minimum MSVC Version
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
if(MSVC_VERSION EQUAL 1800)
|
||||
set(_min_ver "18.0.31101")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
|
||||
message(FATAL_ERROR
|
||||
"Visual Studio 2013 (Update 4, ${_min_ver}) required, "
|
||||
"found (${CMAKE_CXX_COMPILER_VERSION})")
|
||||
endif()
|
||||
endif()
|
||||
if(MSVC_VERSION EQUAL 1900)
|
||||
set(_min_ver "19.0.24210")
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${_min_ver})
|
||||
message(FATAL_ERROR
|
||||
"Visual Studio 2015 (Update 3, ${_min_ver}) required, "
|
||||
"found (${CMAKE_CXX_COMPILER_VERSION})")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
unset(_min_ver)
|
||||
|
||||
# needed for some MSVC installations
|
||||
# 4099 : PDB 'filename' was not found with 'object/library'
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " /SAFESEH:NO /ignore:4099")
|
||||
@@ -158,7 +137,7 @@ endif()
|
||||
|
||||
|
||||
# C++ standards conformace (/permissive-) is available on msvc 15.5 (1912) and up
|
||||
if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG)
|
||||
if(NOT MSVC_CLANG)
|
||||
string(APPEND CMAKE_CXX_FLAGS " /permissive-")
|
||||
# Two-phase name lookup does not place nicely with OpenMP yet, so disable for now
|
||||
string(APPEND CMAKE_CXX_FLAGS " /Zc:twoPhase-")
|
||||
@@ -218,7 +197,7 @@ unset(SYMBOL_FORMAT)
|
||||
unset(SYMBOL_FORMAT_RELEASE)
|
||||
|
||||
# JMC is available on msvc 15.8 (1915) and up
|
||||
if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
|
||||
if(NOT MSVC_CLANG)
|
||||
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /JMC")
|
||||
endif()
|
||||
|
||||
@@ -251,9 +230,6 @@ if(NOT DEFINED LIBDIR)
|
||||
elseif(MSVC_VERSION GREATER 1919)
|
||||
message(STATUS "Visual Studio 2019 detected.")
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
||||
elseif(MSVC_VERSION GREATER 1909)
|
||||
message(STATUS "Visual Studio 2017 detected.")
|
||||
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/${LIBDIR_BASE}_vc15)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}")
|
||||
@@ -264,10 +240,8 @@ endif()
|
||||
|
||||
include(platform_old_libs_update)
|
||||
|
||||
if(CMAKE_GENERATOR MATCHES "^Visual Studio.+" AND # Only supported in the VS IDE
|
||||
MSVC_VERSION GREATER_EQUAL 1924 AND # Supported for 16.4+
|
||||
WITH_CLANG_TIDY # And Clang Tidy needs to be on
|
||||
)
|
||||
# Only supported in the VS IDE & Clang Tidy needs to be on.
|
||||
if(CMAKE_GENERATOR MATCHES "^Visual Studio.+" AND WITH_CLANG_TIDY)
|
||||
set(CMAKE_VS_GLOBALS
|
||||
"RunCodeAnalysis=false"
|
||||
"EnableMicrosoftCodeAnalysis=false"
|
||||
@@ -278,8 +252,7 @@ endif()
|
||||
|
||||
# Mark libdir as system headers with a lower warn level, to resolve some warnings
|
||||
# that we have very little control over
|
||||
if(MSVC_VERSION GREATER_EQUAL 1914 AND # Available with 15.7+
|
||||
NOT MSVC_CLANG AND # But not for clang
|
||||
if(NOT MSVC_CLANG AND # Available with MSVC 15.7+ but not for CLANG.
|
||||
NOT WITH_WINDOWS_SCCACHE AND # And not when sccache is enabled
|
||||
NOT VS_CLANG_TIDY) # Clang-tidy does not like these options
|
||||
add_compile_options(/experimental:external /external:templates- /external:I "${LIBDIR}" /external:W0)
|
||||
@@ -767,7 +740,7 @@ if(WITH_TBB)
|
||||
endif()
|
||||
|
||||
# used in many places so include globally, like OpenGL
|
||||
blender_include_dirs_sys("${PTHREADS_INCLUDE_DIRS}")
|
||||
include_directories(SYSTEM "${PTHREADS_INCLUDE_DIRS}")
|
||||
|
||||
set(WINTAB_INC ${LIBDIR}/wintab/include)
|
||||
|
||||
@@ -874,8 +847,8 @@ endif()
|
||||
|
||||
if(WINDOWS_PYTHON_DEBUG)
|
||||
# Include the system scripts in the blender_python_system_scripts project.
|
||||
FILE(GLOB_RECURSE inFiles "${CMAKE_SOURCE_DIR}/release/scripts/*.*" )
|
||||
ADD_CUSTOM_TARGET(blender_python_system_scripts SOURCES ${inFiles})
|
||||
file(GLOB_RECURSE inFiles "${CMAKE_SOURCE_DIR}/release/scripts/*.*" )
|
||||
add_custom_target(blender_python_system_scripts SOURCES ${inFiles})
|
||||
foreach(_source IN ITEMS ${inFiles})
|
||||
get_filename_component(_source_path "${_source}" PATH)
|
||||
string(REPLACE "${CMAKE_SOURCE_DIR}/release/scripts/" "" _source_path "${_source_path}")
|
||||
@@ -895,8 +868,8 @@ if(WINDOWS_PYTHON_DEBUG)
|
||||
endif()
|
||||
|
||||
file(TO_CMAKE_PATH ${USER_SCRIPTS_ROOT} USER_SCRIPTS_ROOT)
|
||||
FILE(GLOB_RECURSE inFiles "${USER_SCRIPTS_ROOT}/*.*" )
|
||||
ADD_CUSTOM_TARGET(blender_python_user_scripts SOURCES ${inFiles})
|
||||
file(GLOB_RECURSE inFiles "${USER_SCRIPTS_ROOT}/*.*" )
|
||||
add_custom_target(blender_python_user_scripts SOURCES ${inFiles})
|
||||
foreach(_source IN ITEMS ${inFiles})
|
||||
get_filename_component(_source_path "${_source}" PATH)
|
||||
string(REPLACE "${USER_SCRIPTS_ROOT}" "" _source_path "${_source_path}")
|
||||
|
@@ -134,7 +134,6 @@ batch = batch_for_shader(shader, 'LINES', {"pos": coords})
|
||||
|
||||
|
||||
def draw():
|
||||
shader.bind()
|
||||
shader.uniform_float("color", (1, 1, 0, 1))
|
||||
batch.draw(shader)
|
||||
|
||||
|
@@ -58,7 +58,6 @@ batch = batch_for_shader(
|
||||
|
||||
|
||||
def draw():
|
||||
shader.bind()
|
||||
matrix = bpy.context.region_data.perspective_matrix
|
||||
shader.uniform_float("u_ViewProjectionMatrix", matrix)
|
||||
shader.uniform_float("u_Scale", 10)
|
||||
|
@@ -41,7 +41,6 @@ batch = batch_for_shader(shader, 'TRIS', {"position": coords})
|
||||
|
||||
|
||||
def draw():
|
||||
shader.bind()
|
||||
matrix = bpy.context.region_data.perspective_matrix
|
||||
shader.uniform_float("viewProjectionMatrix", matrix)
|
||||
shader.uniform_float("brightness", 0.5)
|
||||
|
@@ -22,7 +22,6 @@ batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices)
|
||||
|
||||
|
||||
def draw():
|
||||
shader.bind()
|
||||
shader.uniform_float("color", (1, 0, 0, 1))
|
||||
batch.draw(shader)
|
||||
|
||||
|
@@ -18,7 +18,6 @@ batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices)
|
||||
|
||||
|
||||
def draw():
|
||||
shader.bind()
|
||||
shader.uniform_float("color", (0, 0.5, 0.5, 1.0))
|
||||
batch.draw(shader)
|
||||
|
||||
|
@@ -56,7 +56,6 @@ batch = batch_for_shader(
|
||||
|
||||
|
||||
def draw():
|
||||
shader.bind()
|
||||
shader.uniform_sampler("image", texture)
|
||||
batch.draw(shader)
|
||||
|
||||
|
@@ -76,7 +76,6 @@ batch = batch_for_shader(
|
||||
|
||||
|
||||
def draw():
|
||||
shader.bind()
|
||||
shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4))
|
||||
shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix)
|
||||
shader.uniform_sampler("image", offscreen.texture_color)
|
||||
|
@@ -78,9 +78,10 @@ Signal Handlers
|
||||
to cancel a render and a crash log is not written in the event of a crash.
|
||||
|
||||
Startup and Preferences
|
||||
When the ``bpy`` module loads, the file is not empty as you might expect,
|
||||
there is a default cube, camera and light. If you wish to start from a blank file use:
|
||||
``bpy.ops.wm.read_factory_settings(use_empty=True)``.
|
||||
When the ``bpy`` module loads it contains the default startup scene
|
||||
(instead of an "empty" blend-file as you might expect), so there is a default cube, camera and light.
|
||||
|
||||
If you wish to start from an empty file use: ``bpy.ops.wm.read_factory_settings(use_empty=True)``.
|
||||
|
||||
The users startup and preferences are ignored to prevent your local configuration from impacting scripts behavior.
|
||||
The Python module behaves as if ``--factory-startup`` was passed as a command line argument.
|
||||
@@ -101,9 +102,10 @@ Limitations
|
||||
Most constraints of Blender as an application still apply:
|
||||
|
||||
Reloading Unsupported
|
||||
Reloading via ``importlib.reload`` will raise an exception instead of reloading and resetting the module.
|
||||
Reloading the ``bpy`` module via ``importlib.reload`` will raise an exception
|
||||
instead of reloading and resetting the module.
|
||||
|
||||
The operator ``bpy.ops.wm.read_factory_settings()`` can be used to reset the internal state.
|
||||
Instead, the operator ``bpy.ops.wm.read_factory_settings()`` can be used to reset the internal state.
|
||||
|
||||
Single Blend File Restriction
|
||||
Only a single ``.blend`` file can be edited at a time.
|
||||
|
4
extern/gflags/CMakeLists.txt
vendored
4
extern/gflags/CMakeLists.txt
vendored
@@ -3,9 +3,7 @@
|
||||
|
||||
# Too noisy for code we don't maintain.
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(NOT "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "8.0")
|
||||
add_cxx_flag("-Wno-cast-function-type")
|
||||
endif()
|
||||
add_cxx_flag("-Wno-cast-function-type")
|
||||
endif()
|
||||
|
||||
set(INC
|
||||
|
@@ -106,8 +106,7 @@
|
||||
/* Copied from BLI_utils... */
|
||||
/* C++ can't use _Static_assert, expects static_assert() but c++0x only,
|
||||
* Coverity also errors out. */
|
||||
#if (!defined(__cplusplus)) && (!defined(__COVERITY__)) && \
|
||||
(defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) /* gcc4.6+ only */
|
||||
#if (!defined(__cplusplus)) && (!defined(__COVERITY__)) && (defined(__GNUC__)) /* GCC only. */
|
||||
# define ATOMIC_STATIC_ASSERT(a, msg) __extension__ _Static_assert(a, msg);
|
||||
#else
|
||||
/* Code adapted from http://www.pixelbeat.org/programming/gcc/static_assert.html */
|
||||
|
@@ -6,12 +6,8 @@
|
||||
#include "testing/testing.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */
|
||||
# pragma GCC diagnostic error "-Wsign-compare"
|
||||
# endif
|
||||
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408
|
||||
# pragma GCC diagnostic error "-Wsign-conversion"
|
||||
# endif
|
||||
# pragma GCC diagnostic error "-Wsign-compare"
|
||||
# pragma GCC diagnostic error "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@@ -36,7 +36,7 @@ if(WITH_CYCLES_NATIVE_ONLY)
|
||||
)
|
||||
|
||||
if(NOT MSVC)
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_march_native "-march=native")
|
||||
add_check_cxx_compiler_flag(CMAKE_CXX_FLAGS _has_march_native "-march=native")
|
||||
if(_has_march_native)
|
||||
set(CYCLES_KERNEL_FLAGS "-march=native")
|
||||
else()
|
||||
@@ -45,18 +45,18 @@ if(WITH_CYCLES_NATIVE_ONLY)
|
||||
unset(_has_march_native)
|
||||
else()
|
||||
if(NOT MSVC_NATIVE_ARCH_FLAGS)
|
||||
TRY_RUN(
|
||||
arch_run_result
|
||||
arch_compile_result
|
||||
${CMAKE_CURRENT_BINARY_DIR}/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/msvc_arch_flags.c
|
||||
COMPILE_OUTPUT_VARIABLE arch_compile_output
|
||||
RUN_OUTPUT_VARIABLE arch_run_output
|
||||
)
|
||||
if(arch_compile_result AND "${arch_run_result}" EQUAL "0")
|
||||
string(STRIP ${arch_run_output} arch_run_output)
|
||||
set(MSVC_NATIVE_ARCH_FLAGS ${arch_run_output} CACHE STRING "MSVC Native architecture flags")
|
||||
endif()
|
||||
try_run(
|
||||
arch_run_result
|
||||
arch_compile_result
|
||||
${CMAKE_CURRENT_BINARY_DIR}/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/msvc_arch_flags.c
|
||||
COMPILE_OUTPUT_VARIABLE arch_compile_output
|
||||
RUN_OUTPUT_VARIABLE arch_run_output
|
||||
)
|
||||
if(arch_compile_result AND "${arch_run_result}" EQUAL "0")
|
||||
string(STRIP ${arch_run_output} arch_run_output)
|
||||
set(MSVC_NATIVE_ARCH_FLAGS ${arch_run_output} CACHE STRING "MSVC Native architecture flags")
|
||||
endif()
|
||||
endif()
|
||||
set(CYCLES_KERNEL_FLAGS "${MSVC_NATIVE_ARCH_FLAGS}")
|
||||
endif()
|
||||
@@ -347,6 +347,24 @@ if(WITH_OPENCOLORIO)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_PATH_GUIDING)
|
||||
add_definitions(-DWITH_PATH_GUIDING)
|
||||
|
||||
# The level of the guiding integration.
|
||||
# Different levels can be selected to measure the overhead of different stages.
|
||||
# 1 = recording the path segments
|
||||
# 2 = 1 + generating (not storing) sample data from the segments
|
||||
# 3 = 2 + storing the generates sample data
|
||||
# 4 = 3 + training the guiding fields
|
||||
# 5 = 4 + querying the trained guiding for sampling (full path guiding)
|
||||
add_definitions(-DPATH_GUIDING_LEVEL=5)
|
||||
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${OPENPGL_INCLUDE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
# NaN debugging
|
||||
if(WITH_CYCLES_DEBUG_NAN)
|
||||
add_definitions(-DWITH_CYCLES_DEBUG_NAN)
|
||||
@@ -364,7 +382,7 @@ endif()
|
||||
|
||||
# Warnings
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_no_error_unused_macros "-Wno-error=unused-macros")
|
||||
add_check_cxx_compiler_flag(CMAKE_CXX_FLAGS _has_no_error_unused_macros "-Wno-error=unused-macros")
|
||||
unset(_has_no_error_unused_macros)
|
||||
endif()
|
||||
|
||||
|
@@ -13,7 +13,7 @@ def _configure_argument_parser():
|
||||
action='store_true')
|
||||
parser.add_argument("--cycles-device",
|
||||
help="Set the device to use for Cycles, overriding user preferences and the scene setting."
|
||||
"Valid options are 'CPU', 'CUDA', 'OPTIX', 'HIP' or 'METAL'."
|
||||
"Valid options are 'CPU', 'CUDA', 'OPTIX', 'HIP', 'ONEAPI', or 'METAL'."
|
||||
"Additionally, you can append '+CPU' to any GPU type for hybrid rendering.",
|
||||
default=None)
|
||||
return parser
|
||||
@@ -156,6 +156,11 @@ def with_osl():
|
||||
return _cycles.with_osl
|
||||
|
||||
|
||||
def with_path_guiding():
|
||||
import _cycles
|
||||
return _cycles.with_path_guiding
|
||||
|
||||
|
||||
def system_info():
|
||||
import _cycles
|
||||
return _cycles.system_info()
|
||||
|
@@ -179,6 +179,12 @@ enum_view3d_shading_render_pass = (
|
||||
('SAMPLE_COUNT', "Sample Count", "Per-pixel number of samples"),
|
||||
)
|
||||
|
||||
enum_guiding_distribution = (
|
||||
('PARALLAX_AWARE_VMM', "Parallax-Aware VMM", "Use Parallax-aware von Mises-Fisher models as directional distribution", 0),
|
||||
('DIRECTIONAL_QUAD_TREE', "Directional Quad Tree", "Use Directional Quad Trees as directional distribution", 1),
|
||||
('VMM', "VMM", "Use von Mises-Fisher models as directional distribution", 2),
|
||||
)
|
||||
|
||||
|
||||
def enum_openimagedenoise_denoiser(self, context):
|
||||
import _cycles
|
||||
@@ -358,7 +364,9 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
preview_samples: IntProperty(
|
||||
name="Viewport Samples",
|
||||
description="Number of samples to render in the viewport, unlimited if 0",
|
||||
min=0, max=(1 << 24),
|
||||
min=0,
|
||||
soft_min=1,
|
||||
max=(1 << 24),
|
||||
default=1024,
|
||||
)
|
||||
|
||||
@@ -507,6 +515,78 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
default=1.0,
|
||||
)
|
||||
|
||||
use_guiding: BoolProperty(
|
||||
name="Guiding",
|
||||
description="Use path guiding for sampling paths. Path guiding incrementally "
|
||||
"learns the light distribution of the scene and guides path into directions "
|
||||
"with high direct and indirect light contributions",
|
||||
default=False,
|
||||
)
|
||||
|
||||
use_deterministic_guiding: BoolProperty(
|
||||
name="Deterministic",
|
||||
description="Makes path guiding deterministic which means renderings will be"
|
||||
"reproducible with the same pixel values every time. This feature slows down"
|
||||
"training",
|
||||
default=True,
|
||||
)
|
||||
|
||||
guiding_distribution_type: EnumProperty(
|
||||
name="Guiding Distribution Type",
|
||||
description="Type of representation for the guiding distribution",
|
||||
items=enum_guiding_distribution,
|
||||
default='PARALLAX_AWARE_VMM',
|
||||
)
|
||||
|
||||
use_surface_guiding: BoolProperty(
|
||||
name="Surface Guiding",
|
||||
description="Use guiding when sampling directions on a surface",
|
||||
default=True,
|
||||
)
|
||||
|
||||
surface_guiding_probability: FloatProperty(
|
||||
name="Surface Guiding Probability",
|
||||
description="The probability of guiding a direction on a surface",
|
||||
min=0.0, max=1.0,
|
||||
default=0.5,
|
||||
)
|
||||
|
||||
use_volume_guiding: BoolProperty(
|
||||
name="Volume Guiding",
|
||||
description="Use guiding when sampling directions inside a volume",
|
||||
default=True,
|
||||
)
|
||||
|
||||
guiding_training_samples: IntProperty(
|
||||
name="Training Samples",
|
||||
description="The maximum number of samples used for training path guiding. "
|
||||
"Higher samples lead to more accurate guiding, however may also unnecessarily slow "
|
||||
"down rendering once guiding is accurate enough. "
|
||||
"A value 0 will continue training until the last sample",
|
||||
min=0,
|
||||
soft_min=1,
|
||||
default=128,
|
||||
)
|
||||
|
||||
volume_guiding_probability: FloatProperty(
|
||||
name="Volume Guiding Probability",
|
||||
description="The probability of guiding a direction inside a volume",
|
||||
min=0.0, max=1.0,
|
||||
default=0.5,
|
||||
)
|
||||
|
||||
use_guiding_direct_light: BoolProperty(
|
||||
name="Guide Direct Light",
|
||||
description="Consider the contribution of directly visible light sources during guiding",
|
||||
default=True,
|
||||
)
|
||||
|
||||
use_guiding_mis_weights: BoolProperty(
|
||||
name="Use MIS Weights",
|
||||
description="Use the MIS weight to weight the contribution of directly visible light sources during guiding",
|
||||
default=True,
|
||||
)
|
||||
|
||||
max_bounces: IntProperty(
|
||||
name="Max Bounces",
|
||||
description="Total maximum number of bounces",
|
||||
@@ -1558,9 +1638,9 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
||||
import sys
|
||||
col.label(text="Requires Intel GPU with Xe-HPG architecture", icon='BLANK1')
|
||||
if sys.platform.startswith("win"):
|
||||
col.label(text="and Windows driver version 101.3268 or newer", icon='BLANK1')
|
||||
col.label(text="and Windows driver version 101.3430 or newer", icon='BLANK1')
|
||||
elif sys.platform.startswith("linux"):
|
||||
col.label(text="and Linux driver version xx.xx.23570 or newer", icon='BLANK1')
|
||||
col.label(text="and Linux driver version xx.xx.23904 or newer", icon='BLANK1')
|
||||
elif device_type == 'METAL':
|
||||
col.label(text="Requires Apple Silicon with macOS 12.2 or newer", icon='BLANK1')
|
||||
col.label(text="or AMD with macOS 12.3 or newer", icon='BLANK1')
|
||||
|
@@ -278,6 +278,63 @@ class CYCLES_RENDER_PT_sampling_render_denoise(CyclesButtonsPanel, Panel):
|
||||
col.prop(cscene, "denoising_prefilter", text="Prefilter")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_sampling_path_guiding(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Path Guiding"
|
||||
bl_parent_id = "CYCLES_RENDER_PT_sampling"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
from . import engine
|
||||
return use_cpu(context) and engine.with_path_guiding()
|
||||
|
||||
def draw_header(self, context):
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
|
||||
self.layout.prop(cscene, "use_guiding", text="")
|
||||
|
||||
def draw(self, context):
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
layout.active = cscene.use_guiding
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(cscene, "use_surface_guiding")
|
||||
col.prop(cscene, "use_volume_guiding")
|
||||
col.prop(cscene, "guiding_training_samples")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_sampling_path_guiding_debug(CyclesDebugButtonsPanel, Panel):
|
||||
bl_label = "Debug"
|
||||
bl_parent_id = "CYCLES_RENDER_PT_sampling_path_guiding"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw(self, context):
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
layout.use_property_decorate = False
|
||||
layout.active = cscene.use_guiding
|
||||
|
||||
layout.prop(cscene, "guiding_distribution_type", text="Distribution Type")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(cscene, "surface_guiding_probability")
|
||||
col.prop(cscene, "volume_guiding_probability")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(cscene, "use_deterministic_guiding")
|
||||
col.prop(cscene, "use_guiding_direct_light")
|
||||
col.prop(cscene, "use_guiding_mis_weights")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_sampling_advanced(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Advanced"
|
||||
bl_parent_id = "CYCLES_RENDER_PT_sampling"
|
||||
@@ -2286,6 +2343,8 @@ classes = (
|
||||
CYCLES_RENDER_PT_sampling_viewport_denoise,
|
||||
CYCLES_RENDER_PT_sampling_render,
|
||||
CYCLES_RENDER_PT_sampling_render_denoise,
|
||||
CYCLES_RENDER_PT_sampling_path_guiding,
|
||||
CYCLES_RENDER_PT_sampling_path_guiding_debug,
|
||||
CYCLES_RENDER_PT_sampling_advanced,
|
||||
CYCLES_RENDER_PT_light_paths,
|
||||
CYCLES_RENDER_PT_light_paths_max_bounces,
|
||||
|
@@ -1084,23 +1084,23 @@ static void create_subd_mesh(Scene *scene,
|
||||
|
||||
const int edges_num = b_mesh.edges.length();
|
||||
|
||||
if (edges_num != 0) {
|
||||
if (edges_num != 0 && b_mesh.edge_creases.length() > 0) {
|
||||
size_t num_creases = 0;
|
||||
const MEdge *edges = static_cast<MEdge *>(b_mesh.edges[0].ptr.data);
|
||||
const float *creases = static_cast<float *>(b_mesh.edge_creases[0].ptr.data);
|
||||
|
||||
for (int i = 0; i < edges_num; i++) {
|
||||
const MEdge &b_edge = edges[i];
|
||||
if (b_edge.crease != 0) {
|
||||
if (creases[i] != 0.0f) {
|
||||
num_creases++;
|
||||
}
|
||||
}
|
||||
|
||||
mesh->reserve_subd_creases(num_creases);
|
||||
|
||||
const MEdge *edges = static_cast<MEdge *>(b_mesh.edges[0].ptr.data);
|
||||
for (int i = 0; i < edges_num; i++) {
|
||||
const MEdge &b_edge = edges[i];
|
||||
if (b_edge.crease != 0) {
|
||||
mesh->add_edge_crease(b_edge.v1, b_edge.v2, float(b_edge.crease) / 255.0f);
|
||||
if (creases[i] != 0.0f) {
|
||||
const MEdge &b_edge = edges[i];
|
||||
mesh->add_edge_crease(b_edge.v1, b_edge.v2, creases[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "util/debug.h"
|
||||
#include "util/foreach.h"
|
||||
#include "util/guiding.h"
|
||||
#include "util/log.h"
|
||||
#include "util/md5.h"
|
||||
#include "util/opengl.h"
|
||||
@@ -534,7 +535,7 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args)
|
||||
socket_type = "NodeSocketBool";
|
||||
data_type = BL::NodeSocket::type_BOOLEAN;
|
||||
if (param->validdefault) {
|
||||
default_boolean = (bool)param->idefault[0];
|
||||
default_boolean = bool(param->idefault[0]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1008,6 +1009,15 @@ void *CCL_python_module_init()
|
||||
PyModule_AddStringConstant(mod, "osl_version_string", "unknown");
|
||||
#endif
|
||||
|
||||
if (ccl::guiding_supported()) {
|
||||
PyModule_AddObject(mod, "with_path_guiding", Py_True);
|
||||
Py_INCREF(Py_True);
|
||||
}
|
||||
else {
|
||||
PyModule_AddObject(mod, "with_path_guiding", Py_False);
|
||||
Py_INCREF(Py_False);
|
||||
}
|
||||
|
||||
#ifdef WITH_EMBREE
|
||||
PyModule_AddObject(mod, "with_embree", Py_True);
|
||||
Py_INCREF(Py_True);
|
||||
|
@@ -413,6 +413,22 @@ void BlenderSync::sync_integrator(BL::ViewLayer &b_view_layer, bool background)
|
||||
integrator->set_direct_light_sampling_type(direct_light_sampling_type);
|
||||
#endif
|
||||
|
||||
integrator->set_use_guiding(get_boolean(cscene, "use_guiding"));
|
||||
integrator->set_use_surface_guiding(get_boolean(cscene, "use_surface_guiding"));
|
||||
integrator->set_use_volume_guiding(get_boolean(cscene, "use_volume_guiding"));
|
||||
integrator->set_guiding_training_samples(get_int(cscene, "guiding_training_samples"));
|
||||
|
||||
if (use_developer_ui) {
|
||||
integrator->set_deterministic_guiding(get_boolean(cscene, "use_deterministic_guiding"));
|
||||
integrator->set_surface_guiding_probability(get_float(cscene, "surface_guiding_probability"));
|
||||
integrator->set_volume_guiding_probability(get_float(cscene, "volume_guiding_probability"));
|
||||
integrator->set_use_guiding_direct_light(get_boolean(cscene, "use_guiding_direct_light"));
|
||||
integrator->set_use_guiding_mis_weights(get_boolean(cscene, "use_guiding_mis_weights"));
|
||||
GuidingDistributionType guiding_distribution_type = (GuidingDistributionType)get_enum(
|
||||
cscene, "guiding_distribution_type", GUIDING_NUM_TYPES, GUIDING_TYPE_PARALLAX_AWARE_VMM);
|
||||
integrator->set_guiding_distribution_type(guiding_distribution_type);
|
||||
}
|
||||
|
||||
DenoiseParams denoise_params = get_denoise_params(b_scene, b_view_layer, background);
|
||||
|
||||
/* No denoising support for vertex color baking, vertices packed into image
|
||||
@@ -737,6 +753,17 @@ void BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, BL::ViewLayer &b_v
|
||||
pass_add(scene, PASS_DENOISING_DEPTH, "Denoising Depth", PassMode::NOISY);
|
||||
}
|
||||
|
||||
#ifdef WITH_CYCLES_DEBUG
|
||||
b_engine.add_pass("Guiding Color", 3, "RGB", b_view_layer.name().c_str());
|
||||
pass_add(scene, PASS_GUIDING_COLOR, "Guiding Color", PassMode::NOISY);
|
||||
|
||||
b_engine.add_pass("Guiding Probability", 1, "X", b_view_layer.name().c_str());
|
||||
pass_add(scene, PASS_GUIDING_PROBABILITY, "Guiding Probability", PassMode::NOISY);
|
||||
|
||||
b_engine.add_pass("Guiding Average Roughness", 1, "X", b_view_layer.name().c_str());
|
||||
pass_add(scene, PASS_GUIDING_AVG_ROUGHNESS, "Guiding Average Roughness", PassMode::NOISY);
|
||||
#endif
|
||||
|
||||
/* Custom AOV passes. */
|
||||
BL::ViewLayer::aovs_iterator b_aov_iter;
|
||||
for (b_view_layer.aovs.begin(b_aov_iter); b_aov_iter != b_view_layer.aovs.end(); ++b_aov_iter) {
|
||||
|
@@ -69,6 +69,7 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
_set_default(BOOST_ROOT "${_cycles_lib_dir}/boost")
|
||||
_set_default(BLOSC_ROOT_DIR "${_cycles_lib_dir}/blosc")
|
||||
_set_default(EMBREE_ROOT_DIR "${_cycles_lib_dir}/embree")
|
||||
_set_default(EPOXY_ROOT_DIR "${_cycles_lib_dir}/epoxy")
|
||||
_set_default(IMATH_ROOT_DIR "${_cycles_lib_dir}/imath")
|
||||
_set_default(GLEW_ROOT_DIR "${_cycles_lib_dir}/glew")
|
||||
_set_default(JPEG_ROOT "${_cycles_lib_dir}/jpeg")
|
||||
@@ -91,7 +92,11 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
_set_default(USD_ROOT_DIR "${_cycles_lib_dir}/usd")
|
||||
_set_default(WEBP_ROOT_DIR "${_cycles_lib_dir}/webp")
|
||||
_set_default(ZLIB_ROOT "${_cycles_lib_dir}/zlib")
|
||||
_set_default(LEVEL_ZERO_ROOT_DIR "${_cycles_lib_dir}/level-zero")
|
||||
if(WIN32)
|
||||
set(LEVEL_ZERO_ROOT_DIR ${_cycles_lib_dir}/level_zero)
|
||||
else()
|
||||
set(LEVEL_ZERO_ROOT_DIR ${_cycles_lib_dir}/level-zero)
|
||||
endif()
|
||||
_set_default(SYCL_ROOT_DIR "${_cycles_lib_dir}/dpcpp")
|
||||
|
||||
# Ignore system libraries
|
||||
@@ -99,6 +104,10 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
else()
|
||||
unset(_cycles_lib_dir)
|
||||
endif()
|
||||
else()
|
||||
if(EXISTS ${LIBDIR})
|
||||
set(_cycles_lib_dir ${LIBDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
@@ -197,17 +206,17 @@ endif()
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(OPENEXR_INCLUDE_DIR ${OPENEXR_ROOT_DIR}/include)
|
||||
set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_ROOT_DIR}/include/OpenEXR)
|
||||
set(OPENEXR_INCLUDE_DIRS ${OPENEXR_INCLUDE_DIR} ${OPENEXR_ROOT_DIR}/include/OpenEXR ${IMATH_ROOT_DIR}/include ${IMATH_ROOT_DIR}/include/Imath)
|
||||
set(OPENEXR_LIBRARIES
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/OpenEXR_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/OpenEXRCore_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Iex_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Half_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/IlmImf_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/Imath_s.lib
|
||||
optimized ${IMATH_ROOT_DIR}/lib/Imath_s.lib
|
||||
optimized ${OPENEXR_ROOT_DIR}/lib/IlmThread_s.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/OpenEXR_s_d.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/OpenEXRCore_s_d.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/Iex_s_d.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/Half_s_d.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/IlmImf_s_d.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/Imath_s_d.lib
|
||||
debug ${IMATH_ROOT_DIR}/lib/Imath_s_d.lib
|
||||
debug ${OPENEXR_ROOT_DIR}/lib/IlmThread_s_d.lib
|
||||
)
|
||||
else()
|
||||
@@ -264,6 +273,31 @@ if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_OSL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# OpenPGL
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_PATH_GUIDING)
|
||||
if(EXISTS ${_cycles_lib_dir})
|
||||
set(openpgl_DIR ${_cycles_lib_dir}/openpgl/lib/cmake/openpgl)
|
||||
endif()
|
||||
|
||||
find_package(openpgl QUIET)
|
||||
if(openpgl_FOUND)
|
||||
if(WIN32)
|
||||
get_target_property(OPENPGL_LIBRARIES_RELEASE openpgl::openpgl LOCATION_RELEASE)
|
||||
get_target_property(OPENPGL_LIBRARIES_DEBUG openpgl::openpgl LOCATION_DEBUG)
|
||||
set(OPENPGL_LIBRARIES optimized ${OPENPGL_LIBRARIES_RELEASE} debug ${OPENPGL_LIBRARIES_DEBUG})
|
||||
else()
|
||||
get_target_property(OPENPGL_LIBRARIES openpgl::openpgl LOCATION)
|
||||
endif()
|
||||
get_target_property(OPENPGL_INCLUDE_DIR openpgl::openpgl INTERFACE_INCLUDE_DIRECTORIES)
|
||||
else()
|
||||
set(WITH_CYCLES_PATH_GUIDING OFF)
|
||||
message(STATUS "OpenPGL not found, disabling WITH_CYCLES_PATH_GUIDING")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# OpenColorIO
|
||||
###########################################################################
|
||||
@@ -319,8 +353,8 @@ if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if(NOT BOOST_VERSION)
|
||||
message(FATAL_ERROR "Unable to determine Boost version")
|
||||
endif()
|
||||
set(BOOST_POSTFIX "vc141-mt-x64-${BOOST_VERSION}.lib")
|
||||
set(BOOST_DEBUG_POSTFIX "vc141-mt-gd-x64-${BOOST_VERSION}.lib")
|
||||
set(BOOST_POSTFIX "vc142-mt-x64-${BOOST_VERSION}.lib")
|
||||
set(BOOST_DEBUG_POSTFIX "vc142-mt-gd-x64-${BOOST_VERSION}.lib")
|
||||
set(BOOST_LIBRARIES
|
||||
optimized ${BOOST_ROOT}/lib/libboost_date_time-${BOOST_POSTFIX}
|
||||
optimized ${BOOST_ROOT}/lib/libboost_iostreams-${BOOST_POSTFIX}
|
||||
@@ -459,6 +493,7 @@ if(CYCLES_STANDALONE_REPOSITORY AND WITH_CYCLES_NANOVDB)
|
||||
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(NANOVDB_INCLUDE_DIR ${NANOVDB_ROOT_DIR}/include)
|
||||
set(NANOVDB_INCLUDE_DIRS ${NANOVDB_INCLUDE_DIR})
|
||||
else()
|
||||
find_package(NanoVDB REQUIRED)
|
||||
endif()
|
||||
@@ -510,7 +545,7 @@ endif()
|
||||
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
if((WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI) OR
|
||||
WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
WITH_CYCLES_HYDRA_RENDER_DELEGATE)
|
||||
if(MSVC AND EXISTS ${_cycles_lib_dir})
|
||||
set(Epoxy_LIBRARIES "${_cycles_lib_dir}/epoxy/lib/epoxy.lib")
|
||||
set(Epoxy_INCLUDE_DIRS "${_cycles_lib_dir}/epoxy/include")
|
||||
|
@@ -118,6 +118,9 @@ macro(cycles_external_libraries_append libraries)
|
||||
if(WITH_ALEMBIC)
|
||||
list(APPEND ${libraries} ${ALEMBIC_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_PATH_GUIDING)
|
||||
target_link_libraries(${target} ${OPENPGL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
list(APPEND ${libraries}
|
||||
${OPENIMAGEIO_LIBRARIES}
|
||||
@@ -169,13 +172,13 @@ macro(cycles_install_libraries target)
|
||||
FILES
|
||||
${TBB_ROOT_DIR}/bin/tbb_debug${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${OPENVDB_ROOT_DIR}/bin/openvdb_d${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
DESTINATION $<TARGET_FILE_DIR:${target}>)
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
else()
|
||||
install(
|
||||
FILES
|
||||
${TBB_ROOT_DIR}/bin/tbb${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${OPENVDB_ROOT_DIR}/bin/openvdb${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
DESTINATION $<TARGET_FILE_DIR:${target}>)
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
@@ -7,6 +7,7 @@
|
||||
/* Used for `info.denoisers`. */
|
||||
/* TODO(sergey): The denoisers are probably to be moved completely out of the device into their
|
||||
* own class. But until then keep API consistent with how it used to work before. */
|
||||
#include "util/guiding.h"
|
||||
#include "util/openimagedenoise.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -27,6 +28,12 @@ void device_cpu_info(vector<DeviceInfo> &devices)
|
||||
info.has_osl = true;
|
||||
info.has_nanovdb = true;
|
||||
info.has_profiling = true;
|
||||
if (guiding_supported()) {
|
||||
info.has_guiding = true;
|
||||
}
|
||||
else {
|
||||
info.has_guiding = false;
|
||||
}
|
||||
if (openimagedenoise_supported()) {
|
||||
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "util/debug.h"
|
||||
#include "util/foreach.h"
|
||||
#include "util/function.h"
|
||||
#include "util/guiding.h"
|
||||
#include "util/log.h"
|
||||
#include "util/map.h"
|
||||
#include "util/openimagedenoise.h"
|
||||
@@ -278,6 +279,23 @@ void CPUDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
|
||||
Device::build_bvh(bvh, progress, refit);
|
||||
}
|
||||
|
||||
void *CPUDevice::get_guiding_device() const
|
||||
{
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
if (!guiding_device) {
|
||||
if (guiding_device_type() == 8) {
|
||||
guiding_device = make_unique<openpgl::cpp::Device>(PGL_DEVICE_TYPE_CPU_8);
|
||||
}
|
||||
else if (guiding_device_type() == 4) {
|
||||
guiding_device = make_unique<openpgl::cpp::Device>(PGL_DEVICE_TYPE_CPU_4);
|
||||
}
|
||||
}
|
||||
return guiding_device.get();
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPUDevice::get_cpu_kernel_thread_globals(
|
||||
vector<CPUKernelThreadGlobals> &kernel_thread_globals)
|
||||
{
|
||||
|
@@ -26,6 +26,9 @@
|
||||
#include "kernel/osl/globals.h"
|
||||
// clang-format on
|
||||
|
||||
#include "util/guiding.h"
|
||||
#include "util/unique_ptr.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class CPUDevice : public Device {
|
||||
@@ -42,6 +45,9 @@ class CPUDevice : public Device {
|
||||
RTCScene embree_scene = NULL;
|
||||
RTCDevice embree_device;
|
||||
#endif
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
mutable unique_ptr<openpgl::cpp::Device> guiding_device;
|
||||
#endif
|
||||
|
||||
CPUDevice(const DeviceInfo &info_, Stats &stats_, Profiler &profiler_);
|
||||
~CPUDevice();
|
||||
@@ -72,6 +78,8 @@ class CPUDevice : public Device {
|
||||
|
||||
void build_bvh(BVH *bvh, Progress &progress, bool refit) override;
|
||||
|
||||
void *get_guiding_device() const override;
|
||||
|
||||
virtual void get_cpu_kernel_thread_globals(
|
||||
vector<CPUKernelThreadGlobals> &kernel_thread_globals) override;
|
||||
virtual void *get_cpu_osl_memory() override;
|
||||
|
@@ -14,19 +14,23 @@ CPUKernelThreadGlobals::CPUKernelThreadGlobals(const KernelGlobalsCPU &kernel_gl
|
||||
Profiler &cpu_profiler)
|
||||
: KernelGlobalsCPU(kernel_globals), cpu_profiler_(cpu_profiler)
|
||||
{
|
||||
reset_runtime_memory();
|
||||
clear_runtime_pointers();
|
||||
|
||||
#ifdef WITH_OSL
|
||||
OSLGlobals::thread_init(this, static_cast<OSLGlobals *>(osl_globals_memory));
|
||||
#else
|
||||
(void)osl_globals_memory;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
opgl_path_segment_storage = new openpgl::cpp::PathSegmentStorage();
|
||||
#endif
|
||||
}
|
||||
|
||||
CPUKernelThreadGlobals::CPUKernelThreadGlobals(CPUKernelThreadGlobals &&other) noexcept
|
||||
: KernelGlobalsCPU(std::move(other)), cpu_profiler_(other.cpu_profiler_)
|
||||
{
|
||||
other.reset_runtime_memory();
|
||||
other.clear_runtime_pointers();
|
||||
}
|
||||
|
||||
CPUKernelThreadGlobals::~CPUKernelThreadGlobals()
|
||||
@@ -34,6 +38,12 @@ CPUKernelThreadGlobals::~CPUKernelThreadGlobals()
|
||||
#ifdef WITH_OSL
|
||||
OSLGlobals::thread_free(this);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
delete opgl_path_segment_storage;
|
||||
delete opgl_surface_sampling_distribution;
|
||||
delete opgl_volume_sampling_distribution;
|
||||
#endif
|
||||
}
|
||||
|
||||
CPUKernelThreadGlobals &CPUKernelThreadGlobals::operator=(CPUKernelThreadGlobals &&other)
|
||||
@@ -44,16 +54,25 @@ CPUKernelThreadGlobals &CPUKernelThreadGlobals::operator=(CPUKernelThreadGlobals
|
||||
|
||||
*static_cast<KernelGlobalsCPU *>(this) = *static_cast<KernelGlobalsCPU *>(&other);
|
||||
|
||||
other.reset_runtime_memory();
|
||||
other.clear_runtime_pointers();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CPUKernelThreadGlobals::reset_runtime_memory()
|
||||
void CPUKernelThreadGlobals::clear_runtime_pointers()
|
||||
{
|
||||
#ifdef WITH_OSL
|
||||
osl = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
opgl_sample_data_storage = nullptr;
|
||||
opgl_guiding_field = nullptr;
|
||||
|
||||
opgl_path_segment_storage = nullptr;
|
||||
opgl_surface_sampling_distribution = nullptr;
|
||||
opgl_volume_sampling_distribution = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CPUKernelThreadGlobals::start_profiling()
|
||||
|
@@ -36,7 +36,7 @@ class CPUKernelThreadGlobals : public KernelGlobalsCPU {
|
||||
void stop_profiling();
|
||||
|
||||
protected:
|
||||
void reset_runtime_memory();
|
||||
void clear_runtime_pointers();
|
||||
|
||||
Profiler &cpu_profiler_;
|
||||
};
|
||||
|
@@ -79,7 +79,7 @@ bool CUDADeviceQueue::enqueue(DeviceKernel kernel,
|
||||
return false;
|
||||
}
|
||||
|
||||
debug_enqueue(kernel, work_size);
|
||||
debug_enqueue_begin(kernel, work_size);
|
||||
|
||||
const CUDAContextScope scope(cuda_device_);
|
||||
const CUDADeviceKernel &cuda_kernel = cuda_device_->kernels.get(kernel);
|
||||
@@ -121,6 +121,8 @@ bool CUDADeviceQueue::enqueue(DeviceKernel kernel,
|
||||
0),
|
||||
"enqueue");
|
||||
|
||||
debug_enqueue_end();
|
||||
|
||||
return !(cuda_device_->have_error());
|
||||
}
|
||||
|
||||
|
@@ -352,6 +352,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
||||
|
||||
info.has_nanovdb = true;
|
||||
info.has_osl = true;
|
||||
info.has_guiding = true;
|
||||
info.has_profiling = true;
|
||||
info.has_peer_memory = false;
|
||||
info.use_metalrt = false;
|
||||
@@ -399,6 +400,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
||||
/* Accumulate device info. */
|
||||
info.has_nanovdb &= device.has_nanovdb;
|
||||
info.has_osl &= device.has_osl;
|
||||
info.has_guiding &= device.has_guiding;
|
||||
info.has_profiling &= device.has_profiling;
|
||||
info.has_peer_memory |= device.has_peer_memory;
|
||||
info.use_metalrt |= device.use_metalrt;
|
||||
|
@@ -66,6 +66,7 @@ class DeviceInfo {
|
||||
bool display_device; /* GPU is used as a display device. */
|
||||
bool has_nanovdb; /* Support NanoVDB volumes. */
|
||||
bool has_osl; /* Support Open Shading Language. */
|
||||
bool has_guiding; /* Support path guiding. */
|
||||
bool has_profiling; /* Supports runtime collection of profiling info. */
|
||||
bool has_peer_memory; /* GPU has P2P access to memory of another GPU. */
|
||||
bool has_gpu_queue; /* Device supports GPU queue. */
|
||||
@@ -84,6 +85,7 @@ class DeviceInfo {
|
||||
display_device = false;
|
||||
has_nanovdb = false;
|
||||
has_osl = false;
|
||||
has_guiding = false;
|
||||
has_profiling = false;
|
||||
has_peer_memory = false;
|
||||
has_gpu_queue = false;
|
||||
@@ -217,6 +219,15 @@ class Device {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Guiding */
|
||||
|
||||
/* Returns path guiding device handle. */
|
||||
virtual void *get_guiding_device() const
|
||||
{
|
||||
LOG(ERROR) << "Request guiding field from a device which does not support it.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Buffer denoising. */
|
||||
|
||||
/* Returns true if task is fully handled. */
|
||||
|
@@ -79,7 +79,7 @@ bool HIPDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
return false;
|
||||
}
|
||||
|
||||
debug_enqueue(kernel, work_size);
|
||||
debug_enqueue_begin(kernel, work_size);
|
||||
|
||||
const HIPContextScope scope(hip_device_);
|
||||
const HIPDeviceKernel &hip_kernel = hip_device_->kernels.get(kernel);
|
||||
@@ -120,6 +120,8 @@ bool HIPDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
0),
|
||||
"enqueue");
|
||||
|
||||
debug_enqueue_end();
|
||||
|
||||
return !(hip_device_->have_error());
|
||||
}
|
||||
|
||||
|
@@ -308,26 +308,29 @@ MetalKernelPipeline *ShaderCache::get_best_pipeline(DeviceKernel kernel, const M
|
||||
|
||||
bool MetalKernelPipeline::should_use_binary_archive() const
|
||||
{
|
||||
if (auto str = getenv("CYCLES_METAL_DISABLE_BINARY_ARCHIVES")) {
|
||||
if (atoi(str) != 0) {
|
||||
/* Don't archive if we have opted out by env var. */
|
||||
return false;
|
||||
/* Issues with binary archives in older macOS versions. */
|
||||
if (@available(macOS 13.0, *)) {
|
||||
if (auto str = getenv("CYCLES_METAL_DISABLE_BINARY_ARCHIVES")) {
|
||||
if (atoi(str) != 0) {
|
||||
/* Don't archive if we have opted out by env var. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pso_type == PSO_GENERIC) {
|
||||
/* Archive the generic kernels. */
|
||||
return true;
|
||||
}
|
||||
if (pso_type == PSO_GENERIC) {
|
||||
/* Archive the generic kernels. */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (device_kernel >= DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND &&
|
||||
device_kernel <= DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW) {
|
||||
/* Archive all shade kernels - they take a long time to compile. */
|
||||
return true;
|
||||
}
|
||||
if (device_kernel >= DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND &&
|
||||
device_kernel <= DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW) {
|
||||
/* Archive all shade kernels - they take a long time to compile. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* The remaining kernels are all fast to compile. They may get cached by the system shader cache,
|
||||
* but will be quick to regenerate if not. */
|
||||
/* The remaining kernels are all fast to compile. They may get cached by the system shader
|
||||
* cache, but will be quick to regenerate if not. */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -77,7 +77,7 @@ bool OneapiDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
|
||||
void **args = const_cast<void **>(_args.values);
|
||||
|
||||
debug_enqueue(kernel, signed_kernel_work_size);
|
||||
debug_enqueue_begin(kernel, signed_kernel_work_size);
|
||||
assert(signed_kernel_work_size >= 0);
|
||||
size_t kernel_work_size = (size_t)signed_kernel_work_size;
|
||||
|
||||
@@ -97,6 +97,8 @@ bool OneapiDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
oneapi_device_->oneapi_error_message() + "\"");
|
||||
}
|
||||
|
||||
debug_enqueue_end();
|
||||
|
||||
return is_finished_ok;
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,7 @@ bool OptiXDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
return false;
|
||||
}
|
||||
|
||||
debug_enqueue(kernel, work_size);
|
||||
debug_enqueue_begin(kernel, work_size);
|
||||
|
||||
const CUDAContextScope scope(cuda_device_);
|
||||
|
||||
@@ -131,6 +131,8 @@ bool OptiXDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
1,
|
||||
1));
|
||||
|
||||
debug_enqueue_end();
|
||||
|
||||
return !(optix_device->have_error());
|
||||
}
|
||||
|
||||
|
@@ -12,9 +12,13 @@
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
DeviceQueue::DeviceQueue(Device *device)
|
||||
: device(device), last_kernels_enqueued_(0), last_sync_time_(0.0)
|
||||
: device(device),
|
||||
last_kernels_enqueued_(0),
|
||||
last_sync_time_(0.0),
|
||||
is_per_kernel_performance_(false)
|
||||
{
|
||||
DCHECK_NE(device, nullptr);
|
||||
is_per_kernel_performance_ = getenv("CYCLES_DEBUG_PER_KERNEL_PERFORMANCE");
|
||||
}
|
||||
|
||||
DeviceQueue::~DeviceQueue()
|
||||
@@ -33,11 +37,17 @@ DeviceQueue::~DeviceQueue()
|
||||
});
|
||||
|
||||
VLOG_DEVICE_STATS << "GPU queue stats:";
|
||||
double total_time = 0.0;
|
||||
for (const auto &[mask, time] : stats_sorted) {
|
||||
total_time += time;
|
||||
VLOG_DEVICE_STATS << " " << std::setfill(' ') << std::setw(10) << std::fixed
|
||||
<< std::setprecision(5) << std::right << time
|
||||
<< "s: " << device_kernel_mask_as_string(mask);
|
||||
}
|
||||
|
||||
if (is_per_kernel_performance_)
|
||||
VLOG_DEVICE_STATS << "GPU queue total time: " << std::fixed << std::setprecision(5)
|
||||
<< total_time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +60,7 @@ void DeviceQueue::debug_init_execution()
|
||||
last_kernels_enqueued_ = 0;
|
||||
}
|
||||
|
||||
void DeviceQueue::debug_enqueue(DeviceKernel kernel, const int work_size)
|
||||
void DeviceQueue::debug_enqueue_begin(DeviceKernel kernel, const int work_size)
|
||||
{
|
||||
if (VLOG_DEVICE_STATS_IS_ON) {
|
||||
VLOG_DEVICE_STATS << "GPU queue launch " << device_kernel_as_string(kernel) << ", work_size "
|
||||
@@ -60,6 +70,13 @@ void DeviceQueue::debug_enqueue(DeviceKernel kernel, const int work_size)
|
||||
last_kernels_enqueued_ |= (uint64_t(1) << (uint64_t)kernel);
|
||||
}
|
||||
|
||||
void DeviceQueue::debug_enqueue_end()
|
||||
{
|
||||
if (VLOG_DEVICE_STATS_IS_ON && is_per_kernel_performance_) {
|
||||
synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceQueue::debug_synchronize()
|
||||
{
|
||||
if (VLOG_DEVICE_STATS_IS_ON) {
|
||||
@@ -67,7 +84,11 @@ void DeviceQueue::debug_synchronize()
|
||||
const double elapsed_time = new_time - last_sync_time_;
|
||||
VLOG_DEVICE_STATS << "GPU queue synchronize, elapsed " << std::setw(10) << elapsed_time << "s";
|
||||
|
||||
stats_kernel_time_[last_kernels_enqueued_] += elapsed_time;
|
||||
/* There is no sense to have an entries in the performance data
|
||||
* container without related kernel information. */
|
||||
if (last_kernels_enqueued_ != 0) {
|
||||
stats_kernel_time_[last_kernels_enqueued_] += elapsed_time;
|
||||
}
|
||||
|
||||
last_sync_time_ = new_time;
|
||||
}
|
||||
|
@@ -162,7 +162,8 @@ class DeviceQueue {
|
||||
|
||||
/* Implementations call these from the corresponding methods to generate debugging logs. */
|
||||
void debug_init_execution();
|
||||
void debug_enqueue(DeviceKernel kernel, const int work_size);
|
||||
void debug_enqueue_begin(DeviceKernel kernel, const int work_size);
|
||||
void debug_enqueue_end();
|
||||
void debug_synchronize();
|
||||
string debug_active_kernels();
|
||||
|
||||
@@ -172,6 +173,9 @@ class DeviceQueue {
|
||||
double last_sync_time_;
|
||||
/* Accumulated execution time for combinations of kernels launched together. */
|
||||
map<DeviceKernelMask, double> stats_kernel_time_;
|
||||
/* If it is true, then a performance statistics in the debugging logs will have focus on kernels
|
||||
* and an explicit queue synchronization will be added after each kernel execution. */
|
||||
bool is_per_kernel_performance_;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -65,6 +65,12 @@ if(WITH_OPENIMAGEDENOISE)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_PATH_GUIDING)
|
||||
list(APPEND LIB
|
||||
${OPENPGL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
include_directories(${INC})
|
||||
include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
|
32
intern/cycles/integrator/guiding.h
Normal file
32
intern/cycles/integrator/guiding.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/types.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
struct GuidingParams {
|
||||
/* The subset of path guiding parameters that can trigger a creation/rebuild
|
||||
* of the guiding field. */
|
||||
bool use = false;
|
||||
bool use_surface_guiding = false;
|
||||
bool use_volume_guiding = false;
|
||||
|
||||
GuidingDistributionType type = GUIDING_TYPE_PARALLAX_AWARE_VMM;
|
||||
int training_samples = 128;
|
||||
bool deterministic = false;
|
||||
|
||||
GuidingParams() = default;
|
||||
|
||||
bool modified(const GuidingParams &other) const
|
||||
{
|
||||
return !((use == other.use) && (use_surface_guiding == other.use_surface_guiding) &&
|
||||
(use_volume_guiding == other.use_volume_guiding) && (type == other.type) &&
|
||||
(training_samples == other.training_samples) &&
|
||||
(deterministic == other.deterministic));
|
||||
}
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
@@ -185,11 +185,25 @@ void PathTrace::render_pipeline(RenderWork render_work)
|
||||
|
||||
rebalance(render_work);
|
||||
|
||||
/* Prepare all per-thread guiding structures before we start with the next rendering
|
||||
* iteration/progression. */
|
||||
const bool use_guiding = device_scene_->data.integrator.use_guiding;
|
||||
if (use_guiding) {
|
||||
guiding_prepare_structures();
|
||||
}
|
||||
|
||||
path_trace(render_work);
|
||||
if (render_cancel_.is_requested) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Update the guiding field using the training data/samples collected during the rendering
|
||||
* iteration/progression. */
|
||||
const bool train_guiding = device_scene_->data.integrator.train_guiding;
|
||||
if (use_guiding && train_guiding) {
|
||||
guiding_update_structures();
|
||||
}
|
||||
|
||||
adaptive_sample(render_work);
|
||||
if (render_cancel_.is_requested) {
|
||||
return;
|
||||
@@ -1241,4 +1255,122 @@ string PathTrace::full_report() const
|
||||
return result;
|
||||
}
|
||||
|
||||
void PathTrace::set_guiding_params(const GuidingParams &guiding_params, const bool reset)
|
||||
{
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
if (guiding_params_.modified(guiding_params)) {
|
||||
guiding_params_ = guiding_params;
|
||||
|
||||
if (guiding_params_.use) {
|
||||
PGLFieldArguments field_args;
|
||||
switch (guiding_params_.type) {
|
||||
default:
|
||||
/* Parallax-aware von Mises-Fisher mixture models. */
|
||||
case GUIDING_TYPE_PARALLAX_AWARE_VMM: {
|
||||
pglFieldArgumentsSetDefaults(
|
||||
field_args,
|
||||
PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
|
||||
PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_PARALLAX_AWARE_VMM);
|
||||
break;
|
||||
}
|
||||
/* Directional quad-trees. */
|
||||
case GUIDING_TYPE_DIRECTIONAL_QUAD_TREE: {
|
||||
pglFieldArgumentsSetDefaults(
|
||||
field_args,
|
||||
PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
|
||||
PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_QUADTREE);
|
||||
break;
|
||||
}
|
||||
/* von Mises-Fisher mixture models. */
|
||||
case GUIDING_TYPE_VMM: {
|
||||
pglFieldArgumentsSetDefaults(
|
||||
field_args,
|
||||
PGL_SPATIAL_STRUCTURE_TYPE::PGL_SPATIAL_STRUCTURE_KDTREE,
|
||||
PGL_DIRECTIONAL_DISTRIBUTION_TYPE::PGL_DIRECTIONAL_DISTRIBUTION_VMM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
# if OPENPGL_VERSION_MINOR >= 4
|
||||
field_args.deterministic = guiding_params.deterministic;
|
||||
# endif
|
||||
openpgl::cpp::Device *guiding_device = static_cast<openpgl::cpp::Device *>(
|
||||
device_->get_guiding_device());
|
||||
if (guiding_device) {
|
||||
guiding_sample_data_storage_ = make_unique<openpgl::cpp::SampleStorage>();
|
||||
guiding_field_ = make_unique<openpgl::cpp::Field>(guiding_device, field_args);
|
||||
}
|
||||
else {
|
||||
guiding_sample_data_storage_ = nullptr;
|
||||
guiding_field_ = nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
guiding_sample_data_storage_ = nullptr;
|
||||
guiding_field_ = nullptr;
|
||||
}
|
||||
}
|
||||
else if (reset) {
|
||||
if (guiding_field_) {
|
||||
guiding_field_->Reset();
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)guiding_params;
|
||||
(void)reset;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PathTrace::guiding_prepare_structures()
|
||||
{
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
const bool train = (guiding_params_.training_samples == 0) ||
|
||||
(guiding_field_->GetIteration() < guiding_params_.training_samples);
|
||||
|
||||
for (auto &&path_trace_work : path_trace_works_) {
|
||||
path_trace_work->guiding_init_kernel_globals(
|
||||
guiding_field_.get(), guiding_sample_data_storage_.get(), train);
|
||||
}
|
||||
|
||||
if (train) {
|
||||
/* For training the guiding distribution we need to force the number of samples
|
||||
* per update to be limited, for reproducible results and reasonable training size.
|
||||
*
|
||||
* Idea: we could stochastically discard samples with a probability of 1/num_samples_per_update
|
||||
* we can then update only after the num_samples_per_update iterations are rendered. */
|
||||
render_scheduler_.set_limit_samples_per_update(4);
|
||||
}
|
||||
else {
|
||||
render_scheduler_.set_limit_samples_per_update(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PathTrace::guiding_update_structures()
|
||||
{
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
VLOG_WORK << "Update path guiding structures";
|
||||
|
||||
VLOG_DEBUG << "Number of surface samples: " << guiding_sample_data_storage_->GetSizeSurface();
|
||||
VLOG_DEBUG << "Number of volume samples: " << guiding_sample_data_storage_->GetSizeVolume();
|
||||
|
||||
const size_t num_valid_samples = guiding_sample_data_storage_->GetSizeSurface() +
|
||||
guiding_sample_data_storage_->GetSizeVolume();
|
||||
|
||||
/* we wait until we have at least 1024 samples */
|
||||
if (num_valid_samples >= 1024) {
|
||||
# if OPENPGL_VERSION_MINOR < 4
|
||||
const size_t num_samples = 1;
|
||||
guiding_field_->Update(*guiding_sample_data_storage_, num_samples);
|
||||
# else
|
||||
guiding_field_->Update(*guiding_sample_data_storage_);
|
||||
# endif
|
||||
guiding_update_count++;
|
||||
|
||||
VLOG_DEBUG << "Path guiding field valid: " << guiding_field_->Validate();
|
||||
|
||||
guiding_sample_data_storage_->Clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -4,11 +4,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "integrator/denoiser.h"
|
||||
#include "integrator/guiding.h"
|
||||
#include "integrator/pass_accessor.h"
|
||||
#include "integrator/path_trace_work.h"
|
||||
#include "integrator/work_balancer.h"
|
||||
|
||||
#include "session/buffers.h"
|
||||
|
||||
#include "util/function.h"
|
||||
#include "util/guiding.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/unique_ptr.h"
|
||||
#include "util/vector.h"
|
||||
@@ -89,6 +93,10 @@ class PathTrace {
|
||||
* Use this to configure the adaptive sampler before rendering any samples. */
|
||||
void set_adaptive_sampling(const AdaptiveSampling &adaptive_sampling);
|
||||
|
||||
/* Set the parameters for guiding.
|
||||
* Use to setup the guiding structures before each rendering iteration.*/
|
||||
void set_guiding_params(const GuidingParams ¶ms, const bool reset);
|
||||
|
||||
/* Sets output driver for render buffer output. */
|
||||
void set_output_driver(unique_ptr<OutputDriver> driver);
|
||||
|
||||
@@ -205,6 +213,15 @@ class PathTrace {
|
||||
void write_tile_buffer(const RenderWork &render_work);
|
||||
void finalize_full_buffer_on_disk(const RenderWork &render_work);
|
||||
|
||||
/* Updates/initializes the guiding structures after a rendering iteration.
|
||||
* The structures are updated using the training data/samples generated during the previous
|
||||
* rendering iteration */
|
||||
void guiding_update_structures();
|
||||
|
||||
/* Prepares the per-kernel thread related guiding structures (e.g., PathSegmentStorage,
|
||||
* pointers to the global Field and SegmentStorage)*/
|
||||
void guiding_prepare_structures();
|
||||
|
||||
/* Get number of samples in the current state of the render buffers. */
|
||||
int get_num_samples_in_buffer();
|
||||
|
||||
@@ -265,6 +282,22 @@ class PathTrace {
|
||||
/* Denoiser device descriptor which holds the denoised big tile for multi-device workloads. */
|
||||
unique_ptr<PathTraceWork> big_tile_denoise_work_;
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
/* Guiding related attributes */
|
||||
GuidingParams guiding_params_;
|
||||
|
||||
/* The guiding field which holds the representation of the incident radiance field for the
|
||||
* complete scene. */
|
||||
unique_ptr<openpgl::cpp::Field> guiding_field_;
|
||||
|
||||
/* The storage container which holds the training data/samples generated during the last
|
||||
* rendering iteration. */
|
||||
unique_ptr<openpgl::cpp::SampleStorage> guiding_sample_data_storage_;
|
||||
|
||||
/* The number of already performed training iterations for the guiding field.*/
|
||||
int guiding_update_count = 0;
|
||||
#endif
|
||||
|
||||
/* State which is common for all the steps of the render work.
|
||||
* Is brought up to date in the `render()` call and is accessed from all the steps involved into
|
||||
* rendering the work. */
|
||||
|
@@ -140,6 +140,13 @@ class PathTraceWork {
|
||||
return device_;
|
||||
}
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
/* Initializes the per-thread guiding kernel data. */
|
||||
virtual void guiding_init_kernel_globals(void *, void *, const bool)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
PathTraceWork(Device *device,
|
||||
Film *film,
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "device/cpu/kernel.h"
|
||||
#include "device/device.h"
|
||||
|
||||
#include "kernel/film/write.h"
|
||||
#include "kernel/integrator/path_state.h"
|
||||
|
||||
#include "integrator/pass_accessor_cpu.h"
|
||||
@@ -145,6 +146,13 @@ void PathTraceWorkCPU::render_samples_full_pipeline(KernelGlobalsCPU *kernel_glo
|
||||
|
||||
kernels_.integrator_megakernel(kernel_globals, state, render_buffer);
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
if (kernel_globals->data.integrator.train_guiding) {
|
||||
/* Push the generated sample data to the global sample data storage. */
|
||||
guiding_push_sample_data_to_global_storage(kernel_globals, state, render_buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (shadow_catcher_state) {
|
||||
kernels_.integrator_megakernel(kernel_globals, shadow_catcher_state, render_buffer);
|
||||
}
|
||||
@@ -276,4 +284,106 @@ void PathTraceWorkCPU::cryptomatte_postproces()
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
/* Note: It seems that this is called before every rendering iteration/progression and not once per
|
||||
* rendering. May be we find a way to call it only once per rendering. */
|
||||
void PathTraceWorkCPU::guiding_init_kernel_globals(void *guiding_field,
|
||||
void *sample_data_storage,
|
||||
const bool train)
|
||||
{
|
||||
/* Linking the global guiding structures (e.g., Field and SampleStorage) to the per-thread
|
||||
* kernel globals. */
|
||||
for (int thread_index = 0; thread_index < kernel_thread_globals_.size(); thread_index++) {
|
||||
CPUKernelThreadGlobals &kg = kernel_thread_globals_[thread_index];
|
||||
openpgl::cpp::Field *field = (openpgl::cpp::Field *)guiding_field;
|
||||
|
||||
/* Allocate sampling distributions. */
|
||||
kg.opgl_guiding_field = field;
|
||||
|
||||
# if PATH_GUIDING_LEVEL >= 4
|
||||
if (kg.opgl_surface_sampling_distribution) {
|
||||
delete kg.opgl_surface_sampling_distribution;
|
||||
kg.opgl_surface_sampling_distribution = nullptr;
|
||||
}
|
||||
if (kg.opgl_volume_sampling_distribution) {
|
||||
delete kg.opgl_volume_sampling_distribution;
|
||||
kg.opgl_volume_sampling_distribution = nullptr;
|
||||
}
|
||||
|
||||
if (field) {
|
||||
kg.opgl_surface_sampling_distribution = new openpgl::cpp::SurfaceSamplingDistribution(field);
|
||||
kg.opgl_volume_sampling_distribution = new openpgl::cpp::VolumeSamplingDistribution(field);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Reserve storage for training. */
|
||||
kg.data.integrator.train_guiding = train;
|
||||
kg.opgl_sample_data_storage = (openpgl::cpp::SampleStorage *)sample_data_storage;
|
||||
|
||||
if (train) {
|
||||
kg.opgl_path_segment_storage->Reserve(kg.data.integrator.transparent_max_bounce +
|
||||
kg.data.integrator.max_bounce + 3);
|
||||
kg.opgl_path_segment_storage->Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
|
||||
KernelGlobalsCPU *kg, IntegratorStateCPU *state, ccl_global float *ccl_restrict render_buffer)
|
||||
{
|
||||
# ifdef WITH_CYCLES_DEBUG
|
||||
if (VLOG_WORK_IS_ON) {
|
||||
/* Check if the generated path segments contain valid values. */
|
||||
const bool validSegments = kg->opgl_path_segment_storage->ValidateSegments();
|
||||
if (!validSegments) {
|
||||
VLOG_WORK << "Guiding: invalid path segments!";
|
||||
}
|
||||
}
|
||||
|
||||
/* Write debug render pass to validate it matches combined pass. */
|
||||
pgl_vec3f pgl_final_color = kg->opgl_path_segment_storage->CalculatePixelEstimate(false);
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
|
||||
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
|
||||
kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + render_buffer_offset;
|
||||
float3 final_color = make_float3(pgl_final_color.x, pgl_final_color.y, pgl_final_color.z);
|
||||
if (kernel_data.film.pass_guiding_color != PASS_UNUSED) {
|
||||
film_write_pass_float3(buffer + kernel_data.film.pass_guiding_color, final_color);
|
||||
}
|
||||
# else
|
||||
(void)state;
|
||||
(void)render_buffer;
|
||||
# endif
|
||||
|
||||
/* Convert the path segment representation of the random walk into radiance samples. */
|
||||
# if PATH_GUIDING_LEVEL >= 2
|
||||
const bool use_direct_light = kernel_data.integrator.use_guiding_direct_light;
|
||||
const bool use_mis_weights = kernel_data.integrator.use_guiding_mis_weights;
|
||||
kg->opgl_path_segment_storage->PrepareSamples(
|
||||
false, nullptr, use_mis_weights, use_direct_light, false);
|
||||
# endif
|
||||
|
||||
# ifdef WITH_CYCLES_DEBUG
|
||||
/* Check if the training/radiance samples generated py the path segment storage are valid.*/
|
||||
if (VLOG_WORK_IS_ON) {
|
||||
const bool validSamples = kg->opgl_path_segment_storage->ValidateSamples();
|
||||
if (!validSamples) {
|
||||
VLOG_WORK
|
||||
<< "Guiding: path segment storage generated/contains invalid radiance/training samples!";
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
# if PATH_GUIDING_LEVEL >= 3
|
||||
/* Push radiance samples from current random walk/path to the global sample storage. */
|
||||
size_t num_samples = 0;
|
||||
const openpgl::cpp::SampleData *samples = kg->opgl_path_segment_storage->GetSamples(num_samples);
|
||||
kg->opgl_sample_data_storage->AddSamples(samples, num_samples);
|
||||
# endif
|
||||
|
||||
/* Clear storage for the current path, to be ready for the next path. */
|
||||
kg->opgl_path_segment_storage->Clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -16,6 +16,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
struct KernelWorkTile;
|
||||
struct KernelGlobalsCPU;
|
||||
struct IntegratorStateCPU;
|
||||
|
||||
class CPUKernels;
|
||||
|
||||
@@ -50,6 +51,22 @@ class PathTraceWorkCPU : public PathTraceWork {
|
||||
virtual int adaptive_sampling_converge_filter_count_active(float threshold, bool reset) override;
|
||||
virtual void cryptomatte_postproces() override;
|
||||
|
||||
#ifdef WITH_PATH_GUIDING
|
||||
/* Initializes the per-thread guiding kernel data. The function sets the pointers to the
|
||||
* global guiding field and the sample data storage as well es initializes the per-thread
|
||||
* guided sampling distributions (e.g., SurfaceSamplingDistribution and
|
||||
* VolumeSamplingDistribution). */
|
||||
void guiding_init_kernel_globals(void *guiding_field,
|
||||
void *sample_data_storage,
|
||||
const bool train) override;
|
||||
|
||||
/* Pushes the collected training data/samples of a path to the global sample storage.
|
||||
* This function is called at the end of a random walk/path generation. */
|
||||
void guiding_push_sample_data_to_global_storage(KernelGlobalsCPU *kernel_globals,
|
||||
IntegratorStateCPU *state,
|
||||
ccl_global float *ccl_restrict render_buffer);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
/* Core path tracing routine. Renders given work time on the given queue. */
|
||||
void render_samples_full_pipeline(KernelGlobalsCPU *kernel_globals,
|
||||
|
@@ -45,6 +45,11 @@ void RenderScheduler::set_denoiser_params(const DenoiseParams ¶ms)
|
||||
denoiser_params_ = params;
|
||||
}
|
||||
|
||||
void RenderScheduler::set_limit_samples_per_update(const int limit_samples)
|
||||
{
|
||||
limit_samples_per_update_ = limit_samples;
|
||||
}
|
||||
|
||||
void RenderScheduler::set_adaptive_sampling(const AdaptiveSampling &adaptive_sampling)
|
||||
{
|
||||
adaptive_sampling_ = adaptive_sampling;
|
||||
@@ -760,7 +765,13 @@ int RenderScheduler::calculate_num_samples_per_update() const
|
||||
|
||||
const double update_interval_in_seconds = guess_display_update_interval_in_seconds();
|
||||
|
||||
return max(int(num_samples_in_second * update_interval_in_seconds), 1);
|
||||
int num_samples_per_update = max(int(num_samples_in_second * update_interval_in_seconds), 1);
|
||||
|
||||
if (limit_samples_per_update_) {
|
||||
num_samples_per_update = min(limit_samples_per_update_, num_samples_per_update);
|
||||
}
|
||||
|
||||
return num_samples_per_update;
|
||||
}
|
||||
|
||||
int RenderScheduler::get_start_sample_to_path_trace() const
|
||||
@@ -808,7 +819,7 @@ int RenderScheduler::get_num_samples_to_path_trace() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
const int num_samples_per_update = calculate_num_samples_per_update();
|
||||
int num_samples_per_update = calculate_num_samples_per_update();
|
||||
const int path_trace_start_sample = get_start_sample_to_path_trace();
|
||||
|
||||
/* Round number of samples to a power of two, so that division of path states into tiles goes in
|
||||
|
@@ -187,6 +187,8 @@ class RenderScheduler {
|
||||
* times, and so on. */
|
||||
string full_report() const;
|
||||
|
||||
void set_limit_samples_per_update(const int limit_samples);
|
||||
|
||||
protected:
|
||||
/* Check whether all work has been scheduled and time limit was not exceeded.
|
||||
*
|
||||
@@ -450,6 +452,10 @@ class RenderScheduler {
|
||||
* (quadratic dependency from the resolution divider): resolution divider of 2 brings render time
|
||||
* down by a factor of 4. */
|
||||
int calculate_resolution_divider_for_time(double desired_time, double actual_time);
|
||||
|
||||
/* If the number of samples per rendering progression should be limited because of path guiding
|
||||
* being activated or is still inside its training phase */
|
||||
int limit_samples_per_update_ = 0;
|
||||
};
|
||||
|
||||
int calculate_resolution_divider_for_resolution(int width, int height, int resolution);
|
||||
|
@@ -243,6 +243,7 @@ set(SRC_KERNEL_INTEGRATOR_HEADERS
|
||||
integrator/intersect_shadow.h
|
||||
integrator/intersect_subsurface.h
|
||||
integrator/intersect_volume_stack.h
|
||||
integrator/guiding.h
|
||||
integrator/megakernel.h
|
||||
integrator/mnee.h
|
||||
integrator/path_state.h
|
||||
@@ -529,7 +530,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
|
||||
endif()
|
||||
if(DEFINED cuda_nvcc_executable AND DEFINED cuda_toolkit_root_dir)
|
||||
# Compile regular kernel
|
||||
CYCLES_CUDA_KERNEL_ADD(${arch} ${prev_arch} kernel "" "${cuda_sources}" FALSE)
|
||||
cycles_cuda_kernel_add(${arch} ${prev_arch} kernel "" "${cuda_sources}" FALSE)
|
||||
|
||||
if(WITH_CYCLES_CUDA_BUILD_SERIAL)
|
||||
set(prev_arch ${arch})
|
||||
@@ -611,7 +612,7 @@ if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
|
||||
|
||||
foreach(arch ${CYCLES_HIP_BINARIES_ARCH})
|
||||
# Compile regular kernel
|
||||
CYCLES_HIP_KERNEL_ADD(${arch} kernel "" "${hip_sources}" FALSE)
|
||||
cycles_hip_kernel_add(${arch} kernel "" "${hip_sources}" FALSE)
|
||||
endforeach()
|
||||
|
||||
add_custom_target(cycles_kernel_hip ALL DEPENDS ${hip_fatbins})
|
||||
@@ -696,11 +697,11 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES)
|
||||
delayed_install("${CMAKE_CURRENT_BINARY_DIR}" "${output}" ${CYCLES_INSTALL_PATH}/lib)
|
||||
endmacro()
|
||||
|
||||
CYCLES_OPTIX_KERNEL_ADD(
|
||||
cycles_optix_kernel_add(
|
||||
kernel_optix
|
||||
"device/optix/kernel.cu"
|
||||
"")
|
||||
CYCLES_OPTIX_KERNEL_ADD(
|
||||
cycles_optix_kernel_add(
|
||||
kernel_optix_shader_raytrace
|
||||
"device/optix/kernel_shader_raytrace.cu"
|
||||
"--keep-device-functions")
|
||||
@@ -950,8 +951,8 @@ endif()
|
||||
|
||||
# Warnings to avoid using doubles in the kernel.
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_float_conversion "-Werror=float-conversion")
|
||||
ADD_CHECK_CXX_COMPILER_FLAG(CMAKE_CXX_FLAGS _has_cxxflag_double_promotion "-Werror=double-promotion")
|
||||
add_check_cxx_compiler_flag(CMAKE_CXX_FLAGS _has_cxxflag_float_conversion "-Werror=float-conversion")
|
||||
add_check_cxx_compiler_flag(CMAKE_CXX_FLAGS _has_cxxflag_double_promotion "-Werror=double-promotion")
|
||||
unset(_has_cxxflag_float_conversion)
|
||||
unset(_has_cxxflag_double_promotion)
|
||||
endif()
|
||||
|
@@ -53,6 +53,9 @@ ccl_device_inline ccl_private ShaderClosure *bsdf_alloc(ccl_private ShaderData *
|
||||
{
|
||||
kernel_assert(isfinite_safe(weight));
|
||||
|
||||
/* No negative weights allowed. */
|
||||
weight = max(weight, zero_float3());
|
||||
|
||||
const float sample_weight = fabsf(average(weight));
|
||||
|
||||
/* Use comparison this way to help dealing with non-finite weight: if the average is not finite
|
||||
|
@@ -69,7 +69,11 @@ ccl_device_inline float bsdf_get_roughness_squared(ccl_private const ShaderClosu
|
||||
* Yining Karl Li and Brent Burley. */
|
||||
ccl_device_inline float bump_shadowing_term(float3 Ng, float3 N, float3 I)
|
||||
{
|
||||
float g = safe_divide(dot(Ng, I), dot(N, I) * dot(Ng, N));
|
||||
const float cosNI = dot(N, I);
|
||||
if (cosNI < 0.0f) {
|
||||
Ng = -Ng;
|
||||
}
|
||||
float g = safe_divide(dot(Ng, I), cosNI * dot(Ng, N));
|
||||
|
||||
/* If the incoming light is on the unshadowed side, return full brightness. */
|
||||
if (g >= 1.0f) {
|
||||
@@ -98,6 +102,12 @@ ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multipl
|
||||
return val;
|
||||
}
|
||||
|
||||
ccl_device_inline bool bsdf_is_transmission(ccl_private const ShaderClosure *sc,
|
||||
const float3 omega_in)
|
||||
{
|
||||
return dot(sc->N, omega_in) < 0.0f;
|
||||
}
|
||||
|
||||
ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
@@ -105,7 +115,9 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
/* For curves use the smooth normal, particularly for ribbons the geometric
|
||||
* normal gives too much darkening otherwise. */
|
||||
@@ -115,78 +127,131 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
label = bsdf_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
#if defined(__SVM__) || defined(__OSL__)
|
||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
||||
label = bsdf_oren_nayar_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
# ifdef __OSL__
|
||||
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
||||
label = bsdf_phong_ramp_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_phong_ramp_sample(
|
||||
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
||||
label = bsdf_diffuse_ramp_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
# endif
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
label = bsdf_translucent_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
label = bsdf_reflection_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_reflection_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, eta);
|
||||
*sampled_roughness = zero_float2();
|
||||
break;
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
label = bsdf_refraction_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_refraction_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, eta);
|
||||
*sampled_roughness = zero_float2();
|
||||
break;
|
||||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
label = bsdf_transparent_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = zero_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
label = bsdf_microfacet_ggx_sample(kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_microfacet_ggx_sample(
|
||||
kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
label = bsdf_microfacet_multi_ggx_sample(
|
||||
kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, &sd->lcg_state);
|
||||
label = bsdf_microfacet_multi_ggx_sample(kg,
|
||||
sc,
|
||||
Ng,
|
||||
sd->I,
|
||||
randu,
|
||||
randv,
|
||||
eval,
|
||||
omega_in,
|
||||
pdf,
|
||||
&sd->lcg_state,
|
||||
sampled_roughness,
|
||||
eta);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
label = bsdf_microfacet_multi_ggx_glass_sample(
|
||||
kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, &sd->lcg_state);
|
||||
label = bsdf_microfacet_multi_ggx_glass_sample(kg,
|
||||
sc,
|
||||
Ng,
|
||||
sd->I,
|
||||
randu,
|
||||
randv,
|
||||
eval,
|
||||
omega_in,
|
||||
pdf,
|
||||
&sd->lcg_state,
|
||||
sampled_roughness,
|
||||
eta);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
label = bsdf_microfacet_beckmann_sample(
|
||||
kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
kg, sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
label = bsdf_ashikhmin_shirley_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_ashikhmin_shirley_sample(
|
||||
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
label = bsdf_ashikhmin_velvet_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
||||
label = bsdf_diffuse_toon_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
label = bsdf_glossy_toon_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
// double check if this is valid
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
label = bsdf_hair_reflection_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_hair_reflection_sample(
|
||||
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
label = bsdf_hair_transmission_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_hair_transmission_sample(
|
||||
sc, Ng, sd->I, randu, randv, eval, omega_in, pdf, sampled_roughness);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
label = bsdf_principled_hair_sample(kg, sc, sd, randu, randv, eval, omega_in, pdf);
|
||||
label = bsdf_principled_hair_sample(
|
||||
kg, sc, sd, randu, randv, eval, omega_in, pdf, sampled_roughness, eta);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
label = bsdf_principled_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
label = bsdf_principled_sheen_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
|
||||
*sampled_roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
@@ -209,11 +274,12 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
const float frequency_multiplier =
|
||||
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
||||
if (frequency_multiplier > 1.0f) {
|
||||
*eval *= shift_cos_in(dot(*omega_in, sc->N), frequency_multiplier);
|
||||
const float cosNI = dot(*omega_in, sc->N);
|
||||
*eval *= shift_cos_in(cosNI, frequency_multiplier);
|
||||
}
|
||||
if (label & LABEL_DIFFUSE) {
|
||||
if (!isequal(sc->N, sd->N)) {
|
||||
*eval *= bump_shadowing_term((label & LABEL_TRANSMIT) ? -sd->N : sd->N, sc->N, *omega_in);
|
||||
*eval *= bump_shadowing_term(sd->N, sc->N, *omega_in);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -226,6 +292,246 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
|
||||
return label;
|
||||
}
|
||||
|
||||
ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
ccl_private float2 *roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
bool refractive = false;
|
||||
float alpha = 1.0f;
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
#ifdef __SVM__
|
||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
# ifdef __OSL__
|
||||
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
||||
alpha = phong_ramp_exponent_to_roughness(((ccl_private const PhongRampBsdf *)sc)->exponent);
|
||||
*roughness = make_float2(alpha, alpha);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
# endif
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*roughness = zero_float2();
|
||||
*eta = bsdf->ior;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_REFRACTION_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*roughness = zero_float2();
|
||||
// do we need to inverse eta??
|
||||
*eta = bsdf->ior;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
*roughness = zero_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
*eta = refractive ? 1.0f / bsdf->ior : bsdf->ior;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
*eta = bsdf->ior;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
*eta = bsdf->ior;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
||||
*eta = refractive ? 1.0f / bsdf->ior : bsdf->ior;
|
||||
} break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
// double check if this is valid
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
*roughness = make_float2(((ccl_private HairBsdf *)sc)->roughness1,
|
||||
((ccl_private HairBsdf *)sc)->roughness2);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
*roughness = make_float2(((ccl_private HairBsdf *)sc)->roughness1,
|
||||
((ccl_private HairBsdf *)sc)->roughness2);
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
alpha = ((ccl_private PrincipledHairBSDF *)sc)->m0_roughness;
|
||||
*roughness = make_float2(alpha, alpha);
|
||||
*eta = ((ccl_private PrincipledHairBSDF *)sc)->eta;
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
*roughness = one_float2();
|
||||
*eta = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline int bsdf_label(const KernelGlobals kg,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
const float3 omega_in)
|
||||
{
|
||||
/* For curves use the smooth normal, particularly for ribbons the geometric
|
||||
* normal gives too much darkening otherwise. */
|
||||
int label;
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
case CLOSURE_BSSRDF_BURLEY_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_ID:
|
||||
case CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
#ifdef __SVM__
|
||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
# ifdef __OSL__
|
||||
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
||||
label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
# endif
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
label = LABEL_TRANSMIT | LABEL_DIFFUSE;
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
label = LABEL_REFLECT | LABEL_SINGULAR;
|
||||
break;
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
label = LABEL_TRANSMIT | LABEL_SINGULAR;
|
||||
break;
|
||||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
label = LABEL_TRANSMIT | LABEL_TRANSPARENT;
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_REFLECT | LABEL_SINGULAR :
|
||||
LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: {
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
label = (bsdf->alpha_x * bsdf->alpha_y <= 1e-7f) ? LABEL_TRANSMIT | LABEL_SINGULAR :
|
||||
LABEL_TRANSMIT | LABEL_GLOSSY;
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
label = (bsdf_is_transmission(sc, omega_in)) ? LABEL_TRANSMIT | LABEL_GLOSSY :
|
||||
LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
label = LABEL_TRANSMIT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
if (bsdf_is_transmission(sc, omega_in))
|
||||
label = LABEL_TRANSMIT | LABEL_GLOSSY;
|
||||
else
|
||||
label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
label = LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
label = LABEL_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Test if BSDF sample should be treated as transparent for background. */
|
||||
if (label & LABEL_TRANSMIT) {
|
||||
float threshold_squared = kernel_data.background.transparent_roughness_squared_threshold;
|
||||
|
||||
if (threshold_squared >= 0.0f) {
|
||||
if (bsdf_get_specular_roughness_squared(sc) <= threshold_squared) {
|
||||
label |= LABEL_TRANSMIT_TRANSPARENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
#ifndef __KERNEL_CUDA__
|
||||
ccl_device
|
||||
#else
|
||||
@@ -236,179 +542,104 @@ ccl_device_inline
|
||||
ccl_private ShaderData *sd,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
const float3 omega_in,
|
||||
const bool is_transmission,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
Spectrum eval = zero_spectrum();
|
||||
|
||||
if (!is_transmission) {
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
eval = bsdf_diffuse_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
#if defined(__SVM__) || defined(__OSL__)
|
||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
||||
eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
||||
eval = bsdf_oren_nayar_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
# ifdef __OSL__
|
||||
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
||||
eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
||||
eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PHONG_RAMP_ID:
|
||||
eval = bsdf_phong_ramp_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
|
||||
eval = bsdf_diffuse_ramp_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
# endif
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(
|
||||
sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
||||
eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
eval = bsdf_translucent_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
eval = bsdf_reflection_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
eval = bsdf_refraction_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
eval = bsdf_transparent_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_ggx_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_glass_eval(sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_beckmann_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
eval = bsdf_ashikhmin_shirley_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
eval = bsdf_ashikhmin_velvet_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
||||
eval = bsdf_diffuse_toon_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
eval = bsdf_glossy_toon_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
eval = bsdf_hair_reflection_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
eval = bsdf_principled_diffuse_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
eval = bsdf_principled_sheen_eval(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
||||
if (!isequal(sc->N, sd->N)) {
|
||||
eval *= bump_shadowing_term(sd->N, sc->N, omega_in);
|
||||
}
|
||||
}
|
||||
/* Shadow terminator offset. */
|
||||
const float frequency_multiplier =
|
||||
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
||||
if (frequency_multiplier > 1.0f) {
|
||||
eval *= shift_cos_in(dot(omega_in, sc->N), frequency_multiplier);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
||||
if (!isequal(sc->N, sd->N)) {
|
||||
eval *= bump_shadowing_term(sd->N, sc->N, omega_in);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (sc->type) {
|
||||
case CLOSURE_BSDF_DIFFUSE_ID:
|
||||
eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
#if defined(__SVM__) || defined(__OSL__)
|
||||
case CLOSURE_BSDF_OREN_NAYAR_ID:
|
||||
eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_TRANSLUCENT_ID:
|
||||
eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_REFLECTION_ID:
|
||||
eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_REFRACTION_ID:
|
||||
eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_TRANSPARENT_ID:
|
||||
eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(
|
||||
sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
|
||||
eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_GLOSSY_TOON_ID:
|
||||
eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
eval = bsdf_principled_hair_eval(kg, sd, sc, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
|
||||
eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
|
||||
eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
|
||||
eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
|
||||
eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
|
||||
if (!isequal(sc->N, sd->N)) {
|
||||
eval *= bump_shadowing_term(-sd->N, sc->N, omega_in);
|
||||
}
|
||||
|
||||
/* Shadow terminator offset. */
|
||||
const float frequency_multiplier =
|
||||
kernel_data_fetch(objects, sd->object).shadow_terminator_shading_offset;
|
||||
if (frequency_multiplier > 1.0f) {
|
||||
const float cosNI = dot(omega_in, sc->N);
|
||||
if (cosNI >= 0.0f) {
|
||||
eval *= shift_cos_in(cosNI, frequency_multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_CYCLES_DEBUG
|
||||
kernel_assert(*pdf >= 0.0f);
|
||||
kernel_assert(eval.x >= 0.0f && eval.y >= 0.0f && eval.z >= 0.0f);
|
||||
|
@@ -39,11 +39,10 @@ ccl_device_inline float bsdf_ashikhmin_shirley_roughness_to_exponent(float rough
|
||||
return 2.0f / (roughness * roughness) - 2.0f;
|
||||
}
|
||||
|
||||
ccl_device_forceinline Spectrum
|
||||
bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device_forceinline Spectrum bsdf_ashikhmin_shirley_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float3 N = bsdf->N;
|
||||
@@ -53,70 +52,60 @@ bsdf_ashikhmin_shirley_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
|
||||
float out = 0.0f;
|
||||
|
||||
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
|
||||
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f || !(NdotI > 0.0f && NdotO > 0.0f)) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
if (NdotI > 0.0f && NdotO > 0.0f) {
|
||||
NdotI = fmaxf(NdotI, 1e-6f);
|
||||
NdotO = fmaxf(NdotO, 1e-6f);
|
||||
float3 H = normalize(omega_in + I);
|
||||
float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
|
||||
float HdotN = fmaxf(dot(H, N), 1e-6f);
|
||||
|
||||
/* pump from original paper
|
||||
* (first derivative disc., but cancels the HdotI in the pdf nicely) */
|
||||
float pump = 1.0f / fmaxf(1e-6f, (HdotI * fmaxf(NdotO, NdotI)));
|
||||
/* pump from d-brdf paper */
|
||||
/*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */
|
||||
NdotI = fmaxf(NdotI, 1e-6f);
|
||||
NdotO = fmaxf(NdotO, 1e-6f);
|
||||
float3 H = normalize(omega_in + I);
|
||||
float HdotI = fmaxf(fabsf(dot(H, I)), 1e-6f);
|
||||
float HdotN = fmaxf(dot(H, N), 1e-6f);
|
||||
|
||||
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
|
||||
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
||||
/* pump from original paper
|
||||
* (first derivative disc., but cancels the HdotI in the pdf nicely) */
|
||||
float pump = 1.0f / fmaxf(1e-6f, (HdotI * fmaxf(NdotO, NdotI)));
|
||||
/* pump from d-brdf paper */
|
||||
/*float pump = 1.0f / fmaxf(1e-4f, ((NdotO + NdotI) * (NdotO*NdotI))); */
|
||||
|
||||
if (n_x == n_y) {
|
||||
/* isotropic */
|
||||
float e = n_x;
|
||||
float lobe = powf(HdotN, e);
|
||||
float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
|
||||
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
|
||||
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
||||
|
||||
out = NdotO * norm * lobe * pump;
|
||||
/* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper). */
|
||||
*pdf = norm * lobe / HdotI;
|
||||
if (n_x == n_y) {
|
||||
/* isotropic */
|
||||
float e = n_x;
|
||||
float lobe = powf(HdotN, e);
|
||||
float norm = (n_x + 1.0f) / (8.0f * M_PI_F);
|
||||
|
||||
out = NdotO * norm * lobe * pump;
|
||||
/* this is p_h / 4(H.I) (conversion from 'wh measure' to 'wi measure', eq. 8 in paper). */
|
||||
*pdf = norm * lobe / HdotI;
|
||||
}
|
||||
else {
|
||||
/* anisotropic */
|
||||
float3 X, Y;
|
||||
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
|
||||
|
||||
float HdotX = dot(H, X);
|
||||
float HdotY = dot(H, Y);
|
||||
float lobe;
|
||||
if (HdotN < 1.0f) {
|
||||
float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN);
|
||||
lobe = powf(HdotN, e);
|
||||
}
|
||||
else {
|
||||
/* anisotropic */
|
||||
float3 X, Y;
|
||||
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
|
||||
|
||||
float HdotX = dot(H, X);
|
||||
float HdotY = dot(H, Y);
|
||||
float lobe;
|
||||
if (HdotN < 1.0f) {
|
||||
float e = (n_x * HdotX * HdotX + n_y * HdotY * HdotY) / (1.0f - HdotN * HdotN);
|
||||
lobe = powf(HdotN, e);
|
||||
}
|
||||
else {
|
||||
lobe = 1.0f;
|
||||
}
|
||||
float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F);
|
||||
|
||||
out = NdotO * norm * lobe * pump;
|
||||
*pdf = norm * lobe / HdotI;
|
||||
lobe = 1.0f;
|
||||
}
|
||||
float norm = sqrtf((n_x + 1.0f) * (n_y + 1.0f)) / (8.0f * M_PI_F);
|
||||
|
||||
out = NdotO * norm * lobe * pump;
|
||||
*pdf = norm * lobe / HdotI;
|
||||
}
|
||||
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_ashikhmin_shirley_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device_inline void bsdf_ashikhmin_shirley_sample_first_quadrant(float n_x,
|
||||
float n_y,
|
||||
float randu,
|
||||
@@ -137,88 +126,93 @@ ccl_device int bsdf_ashikhmin_shirley_sample(ccl_private const ShaderClosure *sc
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
*sampled_roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
float3 N = bsdf->N;
|
||||
int label = LABEL_REFLECT | LABEL_GLOSSY;
|
||||
|
||||
float NdotI = dot(N, I);
|
||||
if (NdotI > 0.0f) {
|
||||
if (!(NdotI > 0.0f)) {
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
|
||||
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
||||
float n_x = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_x);
|
||||
float n_y = bsdf_ashikhmin_shirley_roughness_to_exponent(bsdf->alpha_y);
|
||||
|
||||
/* get x,y basis on the surface for anisotropy */
|
||||
float3 X, Y;
|
||||
/* get x,y basis on the surface for anisotropy */
|
||||
float3 X, Y;
|
||||
|
||||
if (n_x == n_y)
|
||||
make_orthonormals(N, &X, &Y);
|
||||
else
|
||||
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
|
||||
if (n_x == n_y)
|
||||
make_orthonormals(N, &X, &Y);
|
||||
else
|
||||
make_orthonormals_tangent(N, bsdf->T, &X, &Y);
|
||||
|
||||
/* sample spherical coords for h in tangent space */
|
||||
float phi;
|
||||
float cos_theta;
|
||||
if (n_x == n_y) {
|
||||
/* isotropic sampling */
|
||||
phi = M_2PI_F * randu;
|
||||
cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
|
||||
/* sample spherical coords for h in tangent space */
|
||||
float phi;
|
||||
float cos_theta;
|
||||
if (n_x == n_y) {
|
||||
/* isotropic sampling */
|
||||
phi = M_2PI_F * randu;
|
||||
cos_theta = powf(randv, 1.0f / (n_x + 1.0f));
|
||||
}
|
||||
else {
|
||||
/* anisotropic sampling */
|
||||
if (randu < 0.25f) { /* first quadrant */
|
||||
float remapped_randu = 4.0f * randu;
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
}
|
||||
else {
|
||||
/* anisotropic sampling */
|
||||
if (randu < 0.25f) { /* first quadrant */
|
||||
float remapped_randu = 4.0f * randu;
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
}
|
||||
else if (randu < 0.5f) { /* second quadrant */
|
||||
float remapped_randu = 4.0f * (.5f - randu);
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
phi = M_PI_F - phi;
|
||||
}
|
||||
else if (randu < 0.75f) { /* third quadrant */
|
||||
float remapped_randu = 4.0f * (randu - 0.5f);
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
phi = M_PI_F + phi;
|
||||
}
|
||||
else { /* fourth quadrant */
|
||||
float remapped_randu = 4.0f * (1.0f - randu);
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
phi = 2.0f * M_PI_F - phi;
|
||||
}
|
||||
else if (randu < 0.5f) { /* second quadrant */
|
||||
float remapped_randu = 4.0f * (.5f - randu);
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
phi = M_PI_F - phi;
|
||||
}
|
||||
|
||||
/* get half vector in tangent space */
|
||||
float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
|
||||
float cos_phi = cosf(phi);
|
||||
float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
|
||||
float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta);
|
||||
|
||||
/* half vector to world space */
|
||||
float3 H = h.x * X + h.y * Y + h.z * N;
|
||||
float HdotI = dot(H, I);
|
||||
if (HdotI < 0.0f)
|
||||
H = -H;
|
||||
|
||||
/* reflect I on H to get omega_in */
|
||||
*omega_in = -I + (2.0f * HdotI) * H;
|
||||
|
||||
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
|
||||
/* Some high number for MIS. */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_spectrum(1e6f);
|
||||
label = LABEL_REFLECT | LABEL_SINGULAR;
|
||||
else if (randu < 0.75f) { /* third quadrant */
|
||||
float remapped_randu = 4.0f * (randu - 0.5f);
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
phi = M_PI_F + phi;
|
||||
}
|
||||
else {
|
||||
/* leave the rest to eval_reflect */
|
||||
*eval = bsdf_ashikhmin_shirley_eval_reflect(sc, I, *omega_in, pdf);
|
||||
else { /* fourth quadrant */
|
||||
float remapped_randu = 4.0f * (1.0f - randu);
|
||||
bsdf_ashikhmin_shirley_sample_first_quadrant(
|
||||
n_x, n_y, remapped_randu, randv, &phi, &cos_theta);
|
||||
phi = 2.0f * M_PI_F - phi;
|
||||
}
|
||||
}
|
||||
|
||||
/* get half vector in tangent space */
|
||||
float sin_theta = sqrtf(fmaxf(0.0f, 1.0f - cos_theta * cos_theta));
|
||||
float cos_phi = cosf(phi);
|
||||
float sin_phi = sinf(phi); /* no sqrt(1-cos^2) here b/c it causes artifacts */
|
||||
float3 h = make_float3(sin_theta * cos_phi, sin_theta * sin_phi, cos_theta);
|
||||
|
||||
/* half vector to world space */
|
||||
float3 H = h.x * X + h.y * Y + h.z * N;
|
||||
float HdotI = dot(H, I);
|
||||
if (HdotI < 0.0f)
|
||||
H = -H;
|
||||
|
||||
/* reflect I on H to get omega_in */
|
||||
*omega_in = -I + (2.0f * HdotI) * H;
|
||||
|
||||
if (fmaxf(bsdf->alpha_x, bsdf->alpha_y) <= 1e-4f) {
|
||||
/* Some high number for MIS. */
|
||||
*pdf = 1e6f;
|
||||
*eval = make_spectrum(1e6f);
|
||||
label = LABEL_REFLECT | LABEL_SINGULAR;
|
||||
}
|
||||
else {
|
||||
/* leave the rest to eval */
|
||||
*eval = bsdf_ashikhmin_shirley_eval(sc, I, *omega_in, pdf);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
|
@@ -31,10 +31,10 @@ ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_ashikhmin_velvet_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const VelvetBsdf *bsdf = (ccl_private const VelvetBsdf *)sc;
|
||||
float m_invsigma2 = bsdf->invsigma2;
|
||||
@@ -42,46 +42,37 @@ ccl_device Spectrum bsdf_ashikhmin_velvet_eval_reflect(ccl_private const ShaderC
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
float cosNI = dot(N, omega_in);
|
||||
if (cosNO > 0 && cosNI > 0) {
|
||||
float3 H = normalize(omega_in + I);
|
||||
|
||||
float cosNH = dot(N, H);
|
||||
float cosHO = fabsf(dot(I, H));
|
||||
|
||||
if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
float cosNHdivHO = cosNH / cosHO;
|
||||
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
|
||||
|
||||
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
||||
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
||||
|
||||
float sinNH2 = 1 - cosNH * cosNH;
|
||||
float sinNH4 = sinNH2 * sinNH2;
|
||||
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
||||
|
||||
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
|
||||
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
|
||||
|
||||
float out = 0.25f * (D * G) / cosNO;
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F;
|
||||
return make_spectrum(out);
|
||||
if (!(cosNO > 0 && cosNI > 0)) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
float3 H = normalize(omega_in + I);
|
||||
|
||||
ccl_device Spectrum bsdf_ashikhmin_velvet_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
float cosNH = dot(N, H);
|
||||
float cosHO = fabsf(dot(I, H));
|
||||
|
||||
if (!(fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
float cosNHdivHO = cosNH / cosHO;
|
||||
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
|
||||
|
||||
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
||||
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
||||
|
||||
float sinNH2 = 1 - cosNH * cosNH;
|
||||
float sinNH4 = sinNH2 * sinNH2;
|
||||
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
||||
|
||||
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
|
||||
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
|
||||
|
||||
float out = 0.25f * (D * G) / cosNO;
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F;
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
|
||||
@@ -101,41 +92,42 @@ ccl_device int bsdf_ashikhmin_velvet_sample(ccl_private const ShaderClosure *sc,
|
||||
// distribution over the hemisphere
|
||||
sample_uniform_hemisphere(N, randu, randv, omega_in, pdf);
|
||||
|
||||
if (dot(Ng, *omega_in) > 0) {
|
||||
float3 H = normalize(*omega_in + I);
|
||||
|
||||
float cosNI = dot(N, *omega_in);
|
||||
float cosNO = dot(N, I);
|
||||
float cosNH = dot(N, H);
|
||||
float cosHO = fabsf(dot(I, H));
|
||||
|
||||
if (fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f) {
|
||||
float cosNHdivHO = cosNH / cosHO;
|
||||
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
|
||||
|
||||
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
||||
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
||||
|
||||
float sinNH2 = 1 - cosNH * cosNH;
|
||||
float sinNH4 = sinNH2 * sinNH2;
|
||||
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
||||
|
||||
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
|
||||
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
|
||||
|
||||
float power = 0.25f * (D * G) / cosNO;
|
||||
|
||||
*eval = make_spectrum(power);
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!(dot(Ng, *omega_in) > 0)) {
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
float3 H = normalize(*omega_in + I);
|
||||
|
||||
float cosNI = dot(N, *omega_in);
|
||||
float cosNO = dot(N, I);
|
||||
float cosNH = dot(N, H);
|
||||
float cosHO = fabsf(dot(I, H));
|
||||
|
||||
if (!(fabsf(cosNO) > 1e-5f && fabsf(cosNH) < 1.0f - 1e-5f && cosHO > 1e-5f)) {
|
||||
*pdf = 0.0f;
|
||||
*eval = zero_spectrum();
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
float cosNHdivHO = cosNH / cosHO;
|
||||
cosNHdivHO = fmaxf(cosNHdivHO, 1e-5f);
|
||||
|
||||
float fac1 = 2 * fabsf(cosNHdivHO * cosNO);
|
||||
float fac2 = 2 * fabsf(cosNHdivHO * cosNI);
|
||||
|
||||
float sinNH2 = 1 - cosNH * cosNH;
|
||||
float sinNH4 = sinNH2 * sinNH2;
|
||||
float cotangent2 = (cosNH * cosNH) / sinNH2;
|
||||
|
||||
float D = expf(-cotangent2 * m_invsigma2) * m_invsigma2 * M_1_PI_F / sinNH4;
|
||||
float G = fminf(1.0f, fminf(fac1, fac2)); // TODO: derive G from D analytically
|
||||
|
||||
float power = 0.25f * (D * G) / cosNO;
|
||||
|
||||
*eval = make_spectrum(power);
|
||||
|
||||
return LABEL_REFLECT | LABEL_DIFFUSE;
|
||||
}
|
||||
|
||||
|
@@ -26,10 +26,10 @@ ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
||||
float3 N = bsdf->N;
|
||||
@@ -39,15 +39,6 @@ ccl_device Spectrum bsdf_diffuse_eval_reflect(ccl_private const ShaderClosure *s
|
||||
return make_spectrum(cos_pi);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
float3 I,
|
||||
@@ -81,19 +72,10 @@ ccl_device int bsdf_translucent_setup(ccl_private DiffuseBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_translucent_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_translucent_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_translucent_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
|
||||
float3 N = bsdf->N;
|
||||
|
@@ -47,25 +47,23 @@ ccl_device void bsdf_diffuse_ramp_blur(ccl_private ShaderClosure *sc, float roug
|
||||
{
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_diffuse_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_ramp_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
const DiffuseRampBsdf *bsdf = (const DiffuseRampBsdf *)sc;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
float cos_pi = fmaxf(dot(N, omega_in), 0.0f);
|
||||
*pdf = cos_pi * M_1_PI_F;
|
||||
return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_diffuse_ramp_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
return zero_spectrum();
|
||||
if (cos_pi >= 0.0f) {
|
||||
*pdf = cos_pi * M_1_PI_F;
|
||||
return rgb_to_spectrum(bsdf_diffuse_ramp_get_color(bsdf->colors, cos_pi) * M_1_PI_F);
|
||||
}
|
||||
else {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device int bsdf_diffuse_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
|
@@ -37,12 +37,17 @@ ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_hair_reflection_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
||||
if (dot(bsdf->N, omega_in) < 0.0f) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float offset = bsdf->offset;
|
||||
float3 Tg = bsdf->T;
|
||||
float roughness1 = bsdf->roughness1;
|
||||
@@ -84,30 +89,17 @@ ccl_device Spectrum bsdf_hair_reflection_eval_reflect(ccl_private const ShaderCl
|
||||
return make_spectrum(*pdf);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_hair_transmission_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_hair_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_hair_transmission_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_hair_transmission_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
||||
if (dot(bsdf->N, omega_in) >= 0.0f) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float offset = bsdf->offset;
|
||||
float3 Tg = bsdf->T;
|
||||
float roughness1 = bsdf->roughness1;
|
||||
@@ -155,13 +147,15 @@ ccl_device int bsdf_hair_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness)
|
||||
{
|
||||
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
||||
float offset = bsdf->offset;
|
||||
float3 Tg = bsdf->T;
|
||||
float roughness1 = bsdf->roughness1;
|
||||
float roughness2 = bsdf->roughness2;
|
||||
*sampled_roughness = make_float2(roughness1, roughness2);
|
||||
float Iz = dot(Tg, I);
|
||||
float3 locy = normalize(I - Tg * Iz);
|
||||
float3 locx = cross(locy, Tg);
|
||||
@@ -206,13 +200,15 @@ ccl_device int bsdf_hair_transmission_sample(ccl_private const ShaderClosure *sc
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness)
|
||||
{
|
||||
ccl_private const HairBsdf *bsdf = (ccl_private const HairBsdf *)sc;
|
||||
float offset = bsdf->offset;
|
||||
float3 Tg = bsdf->T;
|
||||
float roughness1 = bsdf->roughness1;
|
||||
float roughness2 = bsdf->roughness2;
|
||||
*sampled_roughness = make_float2(roughness1, roughness2);
|
||||
float Iz = dot(Tg, I);
|
||||
float3 locy = normalize(I - Tg * Iz);
|
||||
float3 locx = cross(locy, Tg);
|
||||
|
@@ -56,13 +56,7 @@ ccl_device_inline float delta_phi(int p, float gamma_o, float gamma_t)
|
||||
/* Remaps the given angle to [-pi, pi]. */
|
||||
ccl_device_inline float wrap_angle(float a)
|
||||
{
|
||||
while (a > M_PI_F) {
|
||||
a -= M_2PI_F;
|
||||
}
|
||||
while (a < -M_PI_F) {
|
||||
a += M_2PI_F;
|
||||
}
|
||||
return a;
|
||||
return (a + M_PI_F) - M_2PI_F * floorf((a + M_PI_F) / M_2PI_F) - M_PI_F;
|
||||
}
|
||||
|
||||
/* Logistic distribution function. */
|
||||
@@ -271,76 +265,72 @@ ccl_device Spectrum bsdf_principled_hair_eval(KernelGlobals kg,
|
||||
kernel_assert(isfinite_safe(sd->P) && isfinite_safe(sd->ray_length));
|
||||
|
||||
ccl_private const PrincipledHairBSDF *bsdf = (ccl_private const PrincipledHairBSDF *)sc;
|
||||
float3 Y = float4_to_float3(bsdf->extra->geom);
|
||||
const float3 Y = float4_to_float3(bsdf->extra->geom);
|
||||
|
||||
float3 X = safe_normalize(sd->dPdu);
|
||||
const float3 X = safe_normalize(sd->dPdu);
|
||||
kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
|
||||
float3 Z = safe_normalize(cross(X, Y));
|
||||
const float3 Z = safe_normalize(cross(X, Y));
|
||||
|
||||
float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
|
||||
float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
const float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
|
||||
const float3 wi = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
|
||||
float sin_theta_o = wo.x;
|
||||
float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||
float phi_o = atan2f(wo.z, wo.y);
|
||||
const float sin_theta_o = wo.x;
|
||||
const float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||
const float phi_o = atan2f(wo.z, wo.y);
|
||||
|
||||
float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||
float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||
const float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||
const float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||
|
||||
float sin_gamma_o = bsdf->extra->geom.w;
|
||||
float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||
float gamma_o = safe_asinf(sin_gamma_o);
|
||||
const float sin_gamma_o = bsdf->extra->geom.w;
|
||||
const float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||
const float gamma_o = safe_asinf(sin_gamma_o);
|
||||
|
||||
float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
|
||||
float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
float gamma_t = safe_asinf(sin_gamma_t);
|
||||
const float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
|
||||
const float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
const float gamma_t = safe_asinf(sin_gamma_t);
|
||||
|
||||
Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
const Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
Spectrum Ap[4];
|
||||
float Ap_energy[4];
|
||||
hair_attenuation(
|
||||
kg, fresnel_dielectric_cos(cos_theta_o * cos_gamma_o, bsdf->eta), T, Ap, Ap_energy);
|
||||
|
||||
float sin_theta_i = wi.x;
|
||||
float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||
float phi_i = atan2f(wi.z, wi.y);
|
||||
const float sin_theta_i = wi.x;
|
||||
const float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||
const float phi_i = atan2f(wi.z, wi.y);
|
||||
|
||||
float phi = phi_i - phi_o;
|
||||
const float phi = phi_i - phi_o;
|
||||
|
||||
float angles[6];
|
||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||
|
||||
Spectrum F;
|
||||
float F_energy;
|
||||
float Mp, Np;
|
||||
Spectrum F = zero_spectrum();
|
||||
float F_energy = 0.0f;
|
||||
|
||||
/* Primary specular (R). */
|
||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
||||
F = Ap[0] * Mp * Np;
|
||||
F_energy = Ap_energy[0] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Transmission (TT). */
|
||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[1] * Mp * Np;
|
||||
F_energy += Ap_energy[1] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[2] * Mp * Np;
|
||||
F_energy += Ap_energy[2] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
const float Mp = longitudinal_scattering(angles[2 * i],
|
||||
angles[2 * i + 1],
|
||||
sin_theta_o,
|
||||
cos_theta_o,
|
||||
(i == 0) ? bsdf->m0_roughness :
|
||||
(i == 1) ? 0.25f * bsdf->v :
|
||||
4.0f * bsdf->v);
|
||||
const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[i] * Mp * Np;
|
||||
F_energy += Ap_energy[i] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
}
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
F_energy += Ap_energy[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
{
|
||||
const float Mp = longitudinal_scattering(
|
||||
sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
const float Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
F_energy += Ap_energy[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
}
|
||||
|
||||
*pdf = F_energy;
|
||||
return F;
|
||||
@@ -354,39 +344,44 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)sc;
|
||||
|
||||
float3 Y = float4_to_float3(bsdf->extra->geom);
|
||||
*sampled_roughness = make_float2(bsdf->m0_roughness, bsdf->m0_roughness);
|
||||
*eta = bsdf->eta;
|
||||
|
||||
float3 X = safe_normalize(sd->dPdu);
|
||||
const float3 Y = float4_to_float3(bsdf->extra->geom);
|
||||
|
||||
const float3 X = safe_normalize(sd->dPdu);
|
||||
kernel_assert(fabsf(dot(X, Y)) < 1e-3f);
|
||||
float3 Z = safe_normalize(cross(X, Y));
|
||||
const float3 Z = safe_normalize(cross(X, Y));
|
||||
|
||||
float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
|
||||
const float3 wo = make_float3(dot(sd->I, X), dot(sd->I, Y), dot(sd->I, Z));
|
||||
|
||||
float2 u[2];
|
||||
u[0] = make_float2(randu, randv);
|
||||
u[1].x = lcg_step_float(&sd->lcg_state);
|
||||
u[1].y = lcg_step_float(&sd->lcg_state);
|
||||
|
||||
float sin_theta_o = wo.x;
|
||||
float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||
float phi_o = atan2f(wo.z, wo.y);
|
||||
const float sin_theta_o = wo.x;
|
||||
const float cos_theta_o = cos_from_sin(sin_theta_o);
|
||||
const float phi_o = atan2f(wo.z, wo.y);
|
||||
|
||||
float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||
float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||
const float sin_theta_t = sin_theta_o / bsdf->eta;
|
||||
const float cos_theta_t = cos_from_sin(sin_theta_t);
|
||||
|
||||
float sin_gamma_o = bsdf->extra->geom.w;
|
||||
float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||
float gamma_o = safe_asinf(sin_gamma_o);
|
||||
const float sin_gamma_o = bsdf->extra->geom.w;
|
||||
const float cos_gamma_o = cos_from_sin(sin_gamma_o);
|
||||
const float gamma_o = safe_asinf(sin_gamma_o);
|
||||
|
||||
float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
|
||||
float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
float gamma_t = safe_asinf(sin_gamma_t);
|
||||
const float sin_gamma_t = sin_gamma_o * cos_theta_o / sqrtf(sqr(bsdf->eta) - sqr(sin_theta_o));
|
||||
const float cos_gamma_t = cos_from_sin(sin_gamma_t);
|
||||
const float gamma_t = safe_asinf(sin_gamma_t);
|
||||
|
||||
Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
const Spectrum T = exp(-bsdf->sigma * (2.0f * cos_gamma_t / cos_theta_t));
|
||||
Spectrum Ap[4];
|
||||
float Ap_energy[4];
|
||||
hair_attenuation(
|
||||
@@ -409,7 +404,7 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
||||
}
|
||||
|
||||
u[1].x = max(u[1].x, 1e-5f);
|
||||
float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v));
|
||||
const float fac = 1.0f + v * logf(u[1].x + (1.0f - u[1].x) * expf(-2.0f / v));
|
||||
float sin_theta_i = -fac * sin_theta_o +
|
||||
cos_from_sin(fac) * cosf(M_2PI_F * u[1].y) * cos_theta_o;
|
||||
float cos_theta_i = cos_from_sin(sin_theta_i);
|
||||
@@ -428,41 +423,37 @@ ccl_device int bsdf_principled_hair_sample(KernelGlobals kg,
|
||||
else {
|
||||
phi = M_2PI_F * u[0].y;
|
||||
}
|
||||
float phi_i = phi_o + phi;
|
||||
const float phi_i = phi_o + phi;
|
||||
|
||||
hair_alpha_angles(sin_theta_i, cos_theta_i, bsdf->alpha, angles);
|
||||
|
||||
Spectrum F;
|
||||
float F_energy;
|
||||
float Mp, Np;
|
||||
Spectrum F = zero_spectrum();
|
||||
float F_energy = 0.0f;
|
||||
|
||||
/* Primary specular (R). */
|
||||
Mp = longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->m0_roughness);
|
||||
Np = azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t);
|
||||
F = Ap[0] * Mp * Np;
|
||||
F_energy = Ap_energy[0] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Transmission (TT). */
|
||||
Mp = longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[1] * Mp * Np;
|
||||
F_energy += Ap_energy[1] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
|
||||
/* Secondary specular (TRT). */
|
||||
Mp = longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[2] * Mp * Np;
|
||||
F_energy += Ap_energy[2] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
/* Primary specular (R), Transmission (TT) and Secondary Specular (TRT). */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
const float Mp = longitudinal_scattering(angles[2 * i],
|
||||
angles[2 * i + 1],
|
||||
sin_theta_o,
|
||||
cos_theta_o,
|
||||
(i == 0) ? bsdf->m0_roughness :
|
||||
(i == 1) ? 0.25f * bsdf->v :
|
||||
4.0f * bsdf->v);
|
||||
const float Np = azimuthal_scattering(phi, i, bsdf->s, gamma_o, gamma_t);
|
||||
F += Ap[i] * Mp * Np;
|
||||
F_energy += Ap_energy[i] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
}
|
||||
|
||||
/* Residual component (TRRT+). */
|
||||
Mp = longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
F_energy += Ap_energy[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
{
|
||||
const float Mp = longitudinal_scattering(
|
||||
sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f * bsdf->v);
|
||||
const float Np = M_1_2PI_F;
|
||||
F += Ap[3] * Mp * Np;
|
||||
F_energy += Ap_energy[3] * Mp * Np;
|
||||
kernel_assert(isfinite_safe(F) && isfinite_safe(F_energy));
|
||||
}
|
||||
|
||||
*eval = F;
|
||||
*pdf = F_energy;
|
||||
|
@@ -357,146 +357,129 @@ ccl_device void bsdf_microfacet_ggx_blur(ccl_private ShaderClosure *sc, float ro
|
||||
bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
ccl_device Spectrum bsdf_microfacet_ggx_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
|
||||
const float3 N,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
const float cosNO,
|
||||
const float cosNI)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if (m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
if (!(cosNI > 0 && cosNO > 0)) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
float cosNI = dot(N, omega_in);
|
||||
/* get half vector */
|
||||
float3 m = normalize(omega_in + I);
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
float D, G1o, G1i;
|
||||
|
||||
if (cosNI > 0 && cosNO > 0) {
|
||||
/* get half vector */
|
||||
float3 m = normalize(omega_in + I);
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
float D, G1o, G1i;
|
||||
if (alpha_x == alpha_y) {
|
||||
/* isotropic
|
||||
* eq. 20: (F*G*D)/(4*in*on)
|
||||
* eq. 33: first we calculate D(m) */
|
||||
float cosThetaM = dot(N, m);
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||
|
||||
if (alpha_x == alpha_y) {
|
||||
/* isotropic
|
||||
* eq. 20: (F*G*D)/(4*in*on)
|
||||
* eq. 33: first we calculate D(m) */
|
||||
float cosThetaM = dot(N, m);
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
/* use GTR1 for clearcoat */
|
||||
D = D_GTR1(cosThetaM, bsdf->alpha_x);
|
||||
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
/* use GTR1 for clearcoat */
|
||||
D = D_GTR1(cosThetaM, bsdf->alpha_x);
|
||||
|
||||
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
|
||||
alpha2 = 0.0625f;
|
||||
}
|
||||
else {
|
||||
/* use GTR2 otherwise */
|
||||
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||
}
|
||||
|
||||
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
/* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
|
||||
alpha2 = 0.0625f;
|
||||
}
|
||||
else {
|
||||
/* anisotropic */
|
||||
float3 X, Y, Z = N;
|
||||
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
||||
|
||||
/* distribution */
|
||||
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
|
||||
float slope_x = -local_m.x / (local_m.z * alpha_x);
|
||||
float slope_y = -local_m.y / (local_m.z * alpha_y);
|
||||
float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
|
||||
|
||||
float cosThetaM = local_m.z;
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
|
||||
D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
|
||||
|
||||
/* G1(i,m) and G1(o,m) */
|
||||
float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
|
||||
float cosPhiO = dot(I, X);
|
||||
float sinPhiO = dot(I, Y);
|
||||
|
||||
float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
|
||||
(sinPhiO * sinPhiO) * (alpha_y * alpha_y);
|
||||
alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
|
||||
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
|
||||
|
||||
float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
|
||||
float cosPhiI = dot(omega_in, X);
|
||||
float sinPhiI = dot(omega_in, Y);
|
||||
|
||||
float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
|
||||
(sinPhiI * sinPhiI) * (alpha_y * alpha_y);
|
||||
alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
|
||||
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
|
||||
/* use GTR2 otherwise */
|
||||
D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
|
||||
}
|
||||
|
||||
float G = G1o * G1i;
|
||||
/* eq. 34: now calculate G1(i,m) and G1(o,m) */
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI)));
|
||||
}
|
||||
else {
|
||||
/* anisotropic */
|
||||
float3 X, Y, Z = N;
|
||||
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
||||
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
/* distribution */
|
||||
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
|
||||
float slope_x = -local_m.x / (local_m.z * alpha_x);
|
||||
float slope_y = -local_m.y / (local_m.z * alpha_y);
|
||||
float slope_len = 1 + slope_x * slope_x + slope_y * slope_y;
|
||||
|
||||
Spectrum F = reflection_color(bsdf, omega_in, m);
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
F *= 0.25f * bsdf->extra->clearcoat;
|
||||
}
|
||||
float cosThetaM = local_m.z;
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
|
||||
Spectrum out = F * G * common;
|
||||
D = 1 / ((slope_len * slope_len) * M_PI_F * alpha2 * cosThetaM4);
|
||||
|
||||
/* eq. 2 in distribution of visible normals sampling
|
||||
* `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */
|
||||
/* G1(i,m) and G1(o,m) */
|
||||
float tanThetaO2 = (1 - cosNO * cosNO) / (cosNO * cosNO);
|
||||
float cosPhiO = dot(I, X);
|
||||
float sinPhiO = dot(I, Y);
|
||||
|
||||
/* eq. 38 - but see also:
|
||||
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||
* `pdf = pm * 0.25 / dot(m, I);` */
|
||||
*pdf = G1o * common;
|
||||
float alphaO2 = (cosPhiO * cosPhiO) * (alpha_x * alpha_x) +
|
||||
(sinPhiO * sinPhiO) * (alpha_y * alpha_y);
|
||||
alphaO2 /= cosPhiO * cosPhiO + sinPhiO * sinPhiO;
|
||||
|
||||
return out;
|
||||
G1o = 2 / (1 + safe_sqrtf(1 + alphaO2 * tanThetaO2));
|
||||
|
||||
float tanThetaI2 = (1 - cosNI * cosNI) / (cosNI * cosNI);
|
||||
float cosPhiI = dot(omega_in, X);
|
||||
float sinPhiI = dot(omega_in, Y);
|
||||
|
||||
float alphaI2 = (cosPhiI * cosPhiI) * (alpha_x * alpha_x) +
|
||||
(sinPhiI * sinPhiI) * (alpha_y * alpha_y);
|
||||
alphaI2 /= cosPhiI * cosPhiI + sinPhiI * sinPhiI;
|
||||
|
||||
G1i = 2 / (1 + safe_sqrtf(1 + alphaI2 * tanThetaI2));
|
||||
}
|
||||
|
||||
return zero_spectrum();
|
||||
float G = G1o * G1i;
|
||||
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
|
||||
Spectrum F = reflection_color(bsdf, omega_in, m);
|
||||
if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) {
|
||||
F *= 0.25f * bsdf->extra->clearcoat;
|
||||
}
|
||||
|
||||
Spectrum out = F * G * common;
|
||||
|
||||
/* eq. 2 in distribution of visible normals sampling
|
||||
* `pm = Dw = G1o * dot(m, I) * D / dot(N, I);` */
|
||||
|
||||
/* eq. 38 - but see also:
|
||||
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||
* `pdf = pm * 0.25 / dot(m, I);` */
|
||||
*pdf = G1o * common;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const MicrofacetBsdf *bsdf,
|
||||
const float3 N,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
const float cosNO,
|
||||
const float cosNI)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
float m_eta = bsdf->ior;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if (!m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
float cosNI = dot(N, omega_in);
|
||||
|
||||
if (cosNO <= 0 || cosNI >= 0) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum(); /* vectors on same side -- not possible */
|
||||
}
|
||||
/* compute half-vector of the refraction (eq. 16) */
|
||||
float m_eta = bsdf->ior;
|
||||
float3 ht = -(m_eta * omega_in + I);
|
||||
float3 Ht = normalize(ht);
|
||||
float cosHO = dot(Ht, I);
|
||||
@@ -533,6 +516,30 @@ ccl_device Spectrum bsdf_microfacet_ggx_eval_transmit(ccl_private const ShaderCl
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_ggx_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
const float alpha_x = bsdf->alpha_x;
|
||||
const float alpha_y = bsdf->alpha_y;
|
||||
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
const float3 N = bsdf->N;
|
||||
const float cosNO = dot(N, I);
|
||||
const float cosNI = dot(N, omega_in);
|
||||
|
||||
if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
return (cosNI < 0.0f) ? bsdf_microfacet_ggx_eval_transmit(
|
||||
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
|
||||
bsdf_microfacet_ggx_eval_reflect(
|
||||
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
@@ -541,12 +548,18 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
|
||||
*sampled_roughness = make_float2(alpha_x, alpha_y);
|
||||
*eta = m_refractive ? 1.0f / bsdf->ior : bsdf->ior;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
int label;
|
||||
|
||||
@@ -805,111 +818,95 @@ ccl_device_inline float bsdf_beckmann_aniso_G1(
|
||||
return ((2.181f * a + 3.535f) * a) / ((2.577f * a + 2.276f) * a + 1.0f);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval_reflect(ccl_private const MicrofacetBsdf *bsdf,
|
||||
const float3 N,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
const float cosNO,
|
||||
const float cosNI)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if (m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
if (!(cosNO > 0 && cosNI > 0)) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
float cosNI = dot(N, omega_in);
|
||||
/* get half vector */
|
||||
float3 m = normalize(omega_in + I);
|
||||
|
||||
if (cosNO > 0 && cosNI > 0) {
|
||||
/* get half vector */
|
||||
float3 m = normalize(omega_in + I);
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
float D, G1o, G1i;
|
||||
|
||||
float alpha2 = alpha_x * alpha_y;
|
||||
float D, G1o, G1i;
|
||||
if (alpha_x == alpha_y) {
|
||||
/* isotropic
|
||||
* eq. 20: (F*G*D)/(4*in*on)
|
||||
* eq. 25: first we calculate D(m) */
|
||||
float cosThetaM = dot(N, m);
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
|
||||
|
||||
if (alpha_x == alpha_y) {
|
||||
/* isotropic
|
||||
* eq. 20: (F*G*D)/(4*in*on)
|
||||
* eq. 25: first we calculate D(m) */
|
||||
float cosThetaM = dot(N, m);
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
D = expf(-tanThetaM2 / alpha2) / (M_PI_F * alpha2 * cosThetaM4);
|
||||
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
|
||||
G1o = bsdf_beckmann_G1(alpha_x, cosNO);
|
||||
G1i = bsdf_beckmann_G1(alpha_x, cosNI);
|
||||
}
|
||||
else {
|
||||
/* anisotropic */
|
||||
float3 X, Y, Z = N;
|
||||
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
||||
|
||||
/* eq. 26, 27: now calculate G1(i,m) and G1(o,m) */
|
||||
G1o = bsdf_beckmann_G1(alpha_x, cosNO);
|
||||
G1i = bsdf_beckmann_G1(alpha_x, cosNI);
|
||||
}
|
||||
else {
|
||||
/* anisotropic */
|
||||
float3 X, Y, Z = N;
|
||||
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
||||
/* distribution */
|
||||
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
|
||||
float slope_x = -local_m.x / (local_m.z * alpha_x);
|
||||
float slope_y = -local_m.y / (local_m.z * alpha_y);
|
||||
|
||||
/* distribution */
|
||||
float3 local_m = make_float3(dot(X, m), dot(Y, m), dot(Z, m));
|
||||
float slope_x = -local_m.x / (local_m.z * alpha_x);
|
||||
float slope_y = -local_m.y / (local_m.z * alpha_y);
|
||||
float cosThetaM = local_m.z;
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
|
||||
float cosThetaM = local_m.z;
|
||||
float cosThetaM2 = cosThetaM * cosThetaM;
|
||||
float cosThetaM4 = cosThetaM2 * cosThetaM2;
|
||||
D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
|
||||
|
||||
D = expf(-slope_x * slope_x - slope_y * slope_y) / (M_PI_F * alpha2 * cosThetaM4);
|
||||
|
||||
/* G1(i,m) and G1(o,m) */
|
||||
G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
|
||||
G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
|
||||
}
|
||||
|
||||
float G = G1o * G1i;
|
||||
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
float out = G * common;
|
||||
|
||||
/* eq. 2 in distribution of visible normals sampling
|
||||
* pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
|
||||
|
||||
/* eq. 38 - but see also:
|
||||
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||
* pdf = pm * 0.25 / dot(m, I); */
|
||||
*pdf = G1o * common;
|
||||
|
||||
return make_spectrum(out);
|
||||
/* G1(i,m) and G1(o,m) */
|
||||
G1o = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNO, dot(I, X), dot(I, Y));
|
||||
G1i = bsdf_beckmann_aniso_G1(alpha_x, alpha_y, cosNI, dot(omega_in, X), dot(omega_in, Y));
|
||||
}
|
||||
|
||||
return zero_spectrum();
|
||||
float G = G1o * G1i;
|
||||
|
||||
/* eq. 20 */
|
||||
float common = D * 0.25f / cosNO;
|
||||
float out = G * common;
|
||||
|
||||
/* eq. 2 in distribution of visible normals sampling
|
||||
* pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
|
||||
|
||||
/* eq. 38 - but see also:
|
||||
* eq. 17 in http://www.graphics.cornell.edu/~bjw/wardnotes.pdf
|
||||
* pdf = pm * 0.25 / dot(m, I); */
|
||||
*pdf = G1o * common;
|
||||
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const MicrofacetBsdf *bsdf,
|
||||
const float3 N,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
const float alpha_x,
|
||||
const float alpha_y,
|
||||
const float cosNO,
|
||||
const float cosNI)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
float alpha_y = bsdf->alpha_y;
|
||||
float m_eta = bsdf->ior;
|
||||
bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
if (!m_refractive || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
float cosNI = dot(N, omega_in);
|
||||
|
||||
if (cosNO <= 0 || cosNI >= 0) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
const float m_eta = bsdf->ior;
|
||||
/* compute half-vector of the refraction (eq. 16) */
|
||||
float3 ht = -(m_eta * omega_in + I);
|
||||
float3 Ht = normalize(ht);
|
||||
@@ -944,6 +941,30 @@ ccl_device Spectrum bsdf_microfacet_beckmann_eval_transmit(ccl_private const Sha
|
||||
return make_spectrum(out);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_beckmann_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
const float alpha_x = bsdf->alpha_x;
|
||||
const float alpha_y = bsdf->alpha_y;
|
||||
const bool m_refractive = bsdf->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
||||
const float3 N = bsdf->N;
|
||||
const float cosNO = dot(N, I);
|
||||
const float cosNI = dot(N, omega_in);
|
||||
|
||||
if (((cosNI < 0.0f) != m_refractive) || alpha_x * alpha_y <= 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
return (cosNI < 0.0f) ? bsdf_microfacet_beckmann_eval_transmit(
|
||||
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI) :
|
||||
bsdf_microfacet_beckmann_eval_reflect(
|
||||
bsdf, N, I, omega_in, pdf, alpha_x, alpha_y, cosNO, cosNI);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
@@ -952,7 +973,9 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float alpha_x = bsdf->alpha_x;
|
||||
@@ -961,6 +984,9 @@ ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg,
|
||||
float3 N = bsdf->N;
|
||||
int label;
|
||||
|
||||
*sampled_roughness = make_float2(alpha_x, alpha_y);
|
||||
*eta = m_refractive ? 1.0f / bsdf->ior : bsdf->ior;
|
||||
|
||||
float cosNO = dot(N, I);
|
||||
if (cosNO > 0) {
|
||||
float3 X, Y, Z = N;
|
||||
|
@@ -415,21 +415,11 @@ ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private Microfacet
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
ccl_device Spectrum bsdf_microfacet_multi_ggx_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
@@ -462,6 +452,12 @@ ccl_device Spectrum bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const Sha
|
||||
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
|
||||
else
|
||||
*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
|
||||
|
||||
if (*pdf <= 0.f) {
|
||||
*pdf = 0.f;
|
||||
return make_float3(0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
return mf_eval_glossy(localI,
|
||||
localO,
|
||||
true,
|
||||
@@ -483,7 +479,9 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
ccl_private uint *lcg_state,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
@@ -511,6 +509,9 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
|
||||
|
||||
*eta = bsdf->ior;
|
||||
*sampled_roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
|
||||
bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
|
||||
if (is_aniso)
|
||||
make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
|
||||
@@ -541,6 +542,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg,
|
||||
*pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
|
||||
else
|
||||
*pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
|
||||
*pdf = fmaxf(0.f, *pdf);
|
||||
*eval *= *pdf;
|
||||
|
||||
return LABEL_REFLECT | LABEL_GLOSSY;
|
||||
@@ -576,12 +578,11 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
ccl_device Spectrum
|
||||
bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
ccl_device Spectrum bsdf_microfacet_multi_ggx_glass_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
@@ -597,53 +598,22 @@ bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *s
|
||||
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
|
||||
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
|
||||
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
||||
return mf_eval_glass(localI,
|
||||
localO,
|
||||
false,
|
||||
bsdf->extra->color,
|
||||
bsdf->alpha_x,
|
||||
bsdf->alpha_y,
|
||||
lcg_state,
|
||||
bsdf->ior,
|
||||
false,
|
||||
bsdf->extra->color);
|
||||
}
|
||||
|
||||
ccl_device Spectrum
|
||||
bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
|
||||
|
||||
float3 X, Y, Z;
|
||||
Z = bsdf->N;
|
||||
make_orthonormals(Z, &X, &Y);
|
||||
|
||||
float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
|
||||
float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
|
||||
const bool is_transmission = localO.z < 0.0f;
|
||||
const bool use_fresnel = !is_transmission &&
|
||||
(bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
|
||||
|
||||
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
||||
kernel_assert(*pdf >= 0.f);
|
||||
return mf_eval_glass(localI,
|
||||
localO,
|
||||
true,
|
||||
!is_transmission,
|
||||
bsdf->extra->color,
|
||||
bsdf->alpha_x,
|
||||
bsdf->alpha_y,
|
||||
lcg_state,
|
||||
bsdf->ior,
|
||||
use_fresnel,
|
||||
bsdf->extra->cspec0);
|
||||
(is_transmission) ? bsdf->extra->color : bsdf->extra->cspec0);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
|
||||
@@ -655,13 +625,18 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf,
|
||||
ccl_private uint *lcg_state)
|
||||
ccl_private uint *lcg_state,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
|
||||
float3 X, Y, Z;
|
||||
Z = bsdf->N;
|
||||
|
||||
*eta = bsdf->ior;
|
||||
*sampled_roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y);
|
||||
|
||||
if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
|
||||
float3 R, T;
|
||||
bool inside;
|
||||
@@ -696,6 +671,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg,
|
||||
use_fresnel,
|
||||
bsdf->extra->cspec0);
|
||||
*pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
|
||||
kernel_assert(*pdf >= 0.f);
|
||||
*eval *= *pdf;
|
||||
|
||||
*omega_in = X * localO.x + Y * localO.y + Z * localO.z;
|
||||
|
@@ -47,10 +47,10 @@ ccl_device int bsdf_oren_nayar_setup(ccl_private OrenNayarBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_oren_nayar_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const OrenNayarBsdf *bsdf = (ccl_private const OrenNayarBsdf *)sc;
|
||||
if (dot(bsdf->N, omega_in) > 0.0f) {
|
||||
@@ -63,15 +63,6 @@ ccl_device Spectrum bsdf_oren_nayar_eval_reflect(ccl_private const ShaderClosure
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_oren_nayar_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_oren_nayar_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
float3 I,
|
||||
|
@@ -44,10 +44,10 @@ ccl_device int bsdf_phong_ramp_setup(ccl_private PhongRampBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_phong_ramp_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc;
|
||||
float m_exponent = bsdf->exponent;
|
||||
@@ -70,13 +70,9 @@ ccl_device Spectrum bsdf_phong_ramp_eval_reflect(ccl_private const ShaderClosure
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device float3 bsdf_phong_ramp_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device_inline float phong_ramp_exponent_to_roughness(float exponent)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
return sqrt(1.0f / ((exponent + 2.0f) / 2.0f));
|
||||
}
|
||||
|
||||
ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
@@ -86,11 +82,14 @@ ccl_device int bsdf_phong_ramp_sample(ccl_private const ShaderClosure *sc,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness)
|
||||
{
|
||||
ccl_private const PhongRampBsdf *bsdf = (ccl_private const PhongRampBsdf *)sc;
|
||||
float cosNO = dot(bsdf->N, I);
|
||||
float m_exponent = bsdf->exponent;
|
||||
const float m_roughness = phong_ramp_exponent_to_roughness(m_exponent);
|
||||
*sampled_roughness = make_float2(m_roughness, m_roughness);
|
||||
|
||||
if (cosNO > 0) {
|
||||
// reflect the view vector
|
||||
|
@@ -109,18 +109,17 @@ ccl_device int bsdf_principled_diffuse_setup(ccl_private PrincipledDiffuseBsdf *
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_principled_diffuse_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PrincipledDiffuseBsdf *bsdf = (ccl_private const PrincipledDiffuseBsdf *)sc;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
float3 V = I; // outgoing
|
||||
float3 L = omega_in; // incoming
|
||||
const float3 N = bsdf->N;
|
||||
|
||||
if (dot(N, omega_in) > 0.0f) {
|
||||
const float3 V = I; // outgoing
|
||||
const float3 L = omega_in; // incoming
|
||||
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
return bsdf_principled_diffuse_compute_brdf(bsdf, N, V, L, pdf);
|
||||
}
|
||||
@@ -130,15 +129,6 @@ ccl_device Spectrum bsdf_principled_diffuse_eval_reflect(ccl_private const Shade
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_principled_diffuse_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_diffuse_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
float3 I,
|
||||
|
@@ -59,19 +59,19 @@ ccl_device int bsdf_principled_sheen_setup(ccl_private const ShaderData *sd,
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_principled_sheen_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const PrincipledSheenBsdf *bsdf = (ccl_private const PrincipledSheenBsdf *)sc;
|
||||
|
||||
float3 N = bsdf->N;
|
||||
float3 V = I; // outgoing
|
||||
float3 L = omega_in; // incoming
|
||||
float3 H = normalize(L + V);
|
||||
const float3 N = bsdf->N;
|
||||
|
||||
if (dot(N, omega_in) > 0.0f) {
|
||||
const float3 V = I; // outgoing
|
||||
const float3 L = omega_in; // incoming
|
||||
const float3 H = normalize(L + V);
|
||||
|
||||
*pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
|
||||
return calculate_principled_sheen_brdf(N, V, L, H, pdf);
|
||||
}
|
||||
@@ -81,15 +81,6 @@ ccl_device Spectrum bsdf_principled_sheen_eval_reflect(ccl_private const ShaderC
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_principled_sheen_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_principled_sheen_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
float3 I,
|
||||
|
@@ -18,19 +18,10 @@ ccl_device int bsdf_reflection_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_reflection_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_reflection_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_reflection_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
@@ -43,10 +34,12 @@ ccl_device int bsdf_reflection_sample(ccl_private const ShaderClosure *sc,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float3 N = bsdf->N;
|
||||
*eta = bsdf->ior;
|
||||
|
||||
// only one direction is possible
|
||||
float cosNO = dot(N, I);
|
||||
|
@@ -18,19 +18,10 @@ ccl_device int bsdf_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_refraction_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_refraction_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_refraction_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
@@ -43,10 +34,13 @@ ccl_device int bsdf_refraction_sample(ccl_private const ShaderClosure *sc,
|
||||
float randv,
|
||||
ccl_private Spectrum *eval,
|
||||
ccl_private float3 *omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_private float *pdf,
|
||||
ccl_private float *eta)
|
||||
{
|
||||
ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
|
||||
float m_eta = bsdf->ior;
|
||||
|
||||
*eta = 1.0f / m_eta;
|
||||
float3 N = bsdf->N;
|
||||
|
||||
float3 R, T;
|
||||
|
@@ -49,33 +49,29 @@ ccl_device float bsdf_toon_get_sample_angle(float max_angle, float smooth)
|
||||
return fminf(max_angle + smooth, M_PI_2_F);
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_diffuse_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_diffuse_toon_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
float smooth = bsdf->smooth * M_PI_2_F;
|
||||
float angle = safe_acosf(fmaxf(dot(bsdf->N, omega_in), 0.0f));
|
||||
float cosNI = dot(bsdf->N, omega_in);
|
||||
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
if (cosNI >= 0.0f) {
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
float smooth = bsdf->smooth * M_PI_2_F;
|
||||
float angle = safe_acosf(fmaxf(cosNI, 0.0f));
|
||||
|
||||
if (eval > 0.0f) {
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
float eval = bsdf_toon_get_intensity(max_angle, smooth, angle);
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
||||
return make_spectrum(*pdf * eval);
|
||||
if (eval > 0.0f) {
|
||||
float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth);
|
||||
|
||||
*pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle));
|
||||
return make_spectrum(*pdf * eval);
|
||||
}
|
||||
}
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_diffuse_toon_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
@@ -125,10 +121,10 @@ ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc;
|
||||
float max_angle = bsdf->size * M_PI_2_F;
|
||||
@@ -153,15 +149,6 @@ ccl_device Spectrum bsdf_glossy_toon_eval_reflect(ccl_private const ShaderClosur
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_glossy_toon_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc,
|
||||
float3 Ng,
|
||||
float3 I,
|
||||
|
@@ -59,19 +59,10 @@ ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd,
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_transparent_eval_reflect(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
}
|
||||
|
||||
ccl_device Spectrum bsdf_transparent_eval_transmit(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
ccl_device Spectrum bsdf_transparent_eval(ccl_private const ShaderClosure *sc,
|
||||
const float3 I,
|
||||
const float3 omega_in,
|
||||
ccl_private float *pdf)
|
||||
{
|
||||
*pdf = 0.0f;
|
||||
return zero_spectrum();
|
||||
|
@@ -133,6 +133,10 @@ KERNEL_STRUCT_MEMBER(film, int, pass_bake_primitive)
|
||||
KERNEL_STRUCT_MEMBER(film, int, pass_bake_differential)
|
||||
/* Shadow catcher. */
|
||||
KERNEL_STRUCT_MEMBER(film, int, use_approximate_shadow_catcher)
|
||||
/* Path Guiding */
|
||||
KERNEL_STRUCT_MEMBER(film, int, pass_guiding_color)
|
||||
KERNEL_STRUCT_MEMBER(film, int, pass_guiding_probability)
|
||||
KERNEL_STRUCT_MEMBER(film, int, pass_guiding_avg_roughness)
|
||||
/* Padding. */
|
||||
KERNEL_STRUCT_MEMBER(film, int, pad1)
|
||||
KERNEL_STRUCT_MEMBER(film, int, pad2)
|
||||
@@ -190,8 +194,17 @@ KERNEL_STRUCT_MEMBER(integrator, int, has_shadow_catcher)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, filter_closures)
|
||||
/* MIS debugging. */
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, direct_light_sampling_type)
|
||||
/* Padding */
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, pad1)
|
||||
|
||||
/* Path Guiding */
|
||||
KERNEL_STRUCT_MEMBER(integrator, float, surface_guiding_probability)
|
||||
KERNEL_STRUCT_MEMBER(integrator, float, volume_guiding_probability)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, guiding_distribution_type)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, use_guiding)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, train_guiding)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, use_surface_guiding)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, use_volume_guiding)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, use_guiding_direct_light)
|
||||
KERNEL_STRUCT_MEMBER(integrator, int, use_guiding_mis_weights)
|
||||
KERNEL_STRUCT_END(KernelIntegrator)
|
||||
|
||||
/* SVM. For shader specialization. */
|
||||
|
@@ -9,6 +9,8 @@
|
||||
#include "kernel/types.h"
|
||||
#include "kernel/util/profiling.h"
|
||||
|
||||
#include "util/guiding.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* On the CPU, we pass along the struct KernelGlobals to nearly everywhere in
|
||||
@@ -43,9 +45,20 @@ typedef struct KernelGlobalsCPU {
|
||||
#ifdef __OSL__
|
||||
/* On the CPU, we also have the OSL globals here. Most data structures are shared
|
||||
* with SVM, the difference is in the shaders and object/mesh attributes. */
|
||||
OSLGlobals *osl;
|
||||
OSLShadingSystem *osl_ss;
|
||||
OSLThreadData *osl_tdata;
|
||||
OSLGlobals *osl = nullptr;
|
||||
OSLShadingSystem *osl_ss = nullptr;
|
||||
OSLThreadData *osl_tdata = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef __PATH_GUIDING__
|
||||
/* Pointers to global data structures. */
|
||||
openpgl::cpp::SampleStorage *opgl_sample_data_storage = nullptr;
|
||||
openpgl::cpp::Field *opgl_guiding_field = nullptr;
|
||||
|
||||
/* Local data structures owned by the thread. */
|
||||
openpgl::cpp::PathSegmentStorage *opgl_path_segment_storage = nullptr;
|
||||
openpgl::cpp::SurfaceSamplingDistribution *opgl_surface_sampling_distribution = nullptr;
|
||||
openpgl::cpp::VolumeSamplingDistribution *opgl_volume_sampling_distribution = nullptr;
|
||||
#endif
|
||||
|
||||
/* **** Run-time data **** */
|
||||
|
@@ -29,28 +29,13 @@ using namespace metal::raytracing;
|
||||
|
||||
/* Qualifiers */
|
||||
|
||||
/* Inline everything for Apple GPUs. This gives ~1.1x speedup and 10% spill
|
||||
* reduction for integator_shade_surface. However it comes at the cost of
|
||||
* longer compile times (~4.5 minutes on M1 Max) and is disabled for that
|
||||
* reason, until there is a user option to manually enable it. */
|
||||
|
||||
#if 0 // defined(__KERNEL_METAL_APPLE__)
|
||||
|
||||
# define ccl_device __attribute__((always_inline))
|
||||
# define ccl_device_inline __attribute__((always_inline))
|
||||
# define ccl_device_forceinline __attribute__((always_inline))
|
||||
# define ccl_device_noinline __attribute__((always_inline))
|
||||
|
||||
#define ccl_device
|
||||
#define ccl_device_inline ccl_device __attribute__((always_inline))
|
||||
#define ccl_device_forceinline ccl_device __attribute__((always_inline))
|
||||
#if defined(__KERNEL_METAL_APPLE__)
|
||||
# define ccl_device_noinline ccl_device
|
||||
#else
|
||||
|
||||
# define ccl_device
|
||||
# define ccl_device_inline ccl_device
|
||||
# define ccl_device_forceinline ccl_device
|
||||
# if defined(__KERNEL_METAL_APPLE__)
|
||||
# define ccl_device_noinline ccl_device
|
||||
# else
|
||||
# define ccl_device_noinline ccl_device __attribute__((noinline))
|
||||
# endif
|
||||
# define ccl_device_noinline ccl_device __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
#define ccl_device_noinline_cpu ccl_device
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#define CCL_NAMESPACE_END
|
||||
|
||||
#include <cstdint>
|
||||
#include <math.h>
|
||||
|
||||
#ifndef __NODES_MAX_GROUP__
|
||||
# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX
|
||||
@@ -174,21 +175,15 @@ using sycl::half;
|
||||
#define fmodf(x, y) sycl::fmod((x), (y))
|
||||
#define lgammaf(x) sycl::lgamma((x))
|
||||
|
||||
#define __forceinline __attribute__((always_inline))
|
||||
|
||||
/* Types */
|
||||
#include "util/half.h"
|
||||
#include "util/types.h"
|
||||
|
||||
/* NOTE(@nsirgien): Declaring these functions after types headers is very important because they
|
||||
* include oneAPI headers, which transitively include math.h headers which will cause redefinitions
|
||||
* of the math defines because math.h also uses them and having them defined before math.h include
|
||||
* is actually UB. */
|
||||
/* Use fast math functions - get them from sycl::native namespace for native math function
|
||||
* implementations */
|
||||
#define cosf(x) sycl::native::cos(((float)(x)))
|
||||
#define sinf(x) sycl::native::sin(((float)(x)))
|
||||
#define powf(x, y) sycl::native::powr(((float)(x)), ((float)(y)))
|
||||
#define tanf(x) sycl::native::tan(((float)(x)))
|
||||
#define logf(x) sycl::native::log(((float)(x)))
|
||||
#define expf(x) sycl::native::exp(((float)(x)))
|
||||
|
||||
#define __forceinline __attribute__((always_inline))
|
||||
|
||||
/* Types */
|
||||
#include "util/half.h"
|
||||
#include "util/types.h"
|
||||
|
@@ -668,9 +668,9 @@ bool oneapi_enqueue_kernel(KernelContext *kernel_context,
|
||||
/* Compute-runtime (ie. NEO) version is what gets returned by sycl/L0 on Windows
|
||||
* since Windows driver 101.3268. */
|
||||
/* The same min compute-runtime version is currently required across Windows and Linux.
|
||||
* For Windows driver 101.3268, compute-runtime version is 23570. */
|
||||
static const int lowest_supported_driver_version_win = 1013268;
|
||||
static const int lowest_supported_driver_version_neo = 23570;
|
||||
* For Windows driver 101.3430, compute-runtime version is 23904. */
|
||||
static const int lowest_supported_driver_version_win = 1013430;
|
||||
static const int lowest_supported_driver_version_neo = 23904;
|
||||
|
||||
static int parse_driver_build_version(const sycl::device &device)
|
||||
{
|
||||
|
542
intern/cycles/kernel/integrator/guiding.h
Normal file
542
intern/cycles/kernel/integrator/guiding.h
Normal file
@@ -0,0 +1,542 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright 2011-2022 Blender Foundation */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/closure/alloc.h"
|
||||
#include "kernel/closure/bsdf.h"
|
||||
#include "kernel/film/write.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Utilities. */
|
||||
|
||||
#if defined(__PATH_GUIDING__)
|
||||
static pgl_vec3f guiding_vec3f(const float3 v)
|
||||
{
|
||||
return openpgl::cpp::Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
static pgl_point3f guiding_point3f(const float3 v)
|
||||
{
|
||||
return openpgl::cpp::Point3(v.x, v.y, v.z);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Path recording for guiding. */
|
||||
|
||||
/* Record Surface Interactions */
|
||||
|
||||
/* Records/Adds a new path segment with the current path vertex on a surface.
|
||||
* If the path is not terminated this call is usually followed by a call of
|
||||
* guiding_record_surface_bounce. */
|
||||
ccl_device_forceinline void guiding_record_surface_segment(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private const ShaderData *sd)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pgl_vec3f zero = guiding_vec3f(zero_float3());
|
||||
const pgl_vec3f one = guiding_vec3f(one_float3());
|
||||
|
||||
state->guiding.path_segment = kg->opgl_path_segment_storage->NextSegment();
|
||||
openpgl::cpp::SetPosition(state->guiding.path_segment, guiding_point3f(sd->P));
|
||||
openpgl::cpp::SetDirectionOut(state->guiding.path_segment, guiding_vec3f(sd->I));
|
||||
openpgl::cpp::SetVolumeScatter(state->guiding.path_segment, false);
|
||||
openpgl::cpp::SetScatteredContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetDirectContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, one);
|
||||
openpgl::cpp::SetEta(state->guiding.path_segment, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the surface scattering event at the current vertex position of the segment.*/
|
||||
ccl_device_forceinline void guiding_record_surface_bounce(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private const ShaderData *sd,
|
||||
const Spectrum weight,
|
||||
const float pdf,
|
||||
const float3 N,
|
||||
const float3 omega_in,
|
||||
const float2 roughness,
|
||||
const float eta)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
const float min_roughness = safe_sqrtf(fminf(roughness.x, roughness.y));
|
||||
const bool is_delta = (min_roughness == 0.0f);
|
||||
const float3 weight_rgb = spectrum_to_rgb(weight);
|
||||
const float3 normal = clamp(N, -one_float3(), one_float3());
|
||||
|
||||
kernel_assert(state->guiding.path_segment != nullptr);
|
||||
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, guiding_vec3f(one_float3()));
|
||||
openpgl::cpp::SetVolumeScatter(state->guiding.path_segment, false);
|
||||
openpgl::cpp::SetNormal(state->guiding.path_segment, guiding_vec3f(normal));
|
||||
openpgl::cpp::SetDirectionIn(state->guiding.path_segment, guiding_vec3f(omega_in));
|
||||
openpgl::cpp::SetPDFDirectionIn(state->guiding.path_segment, pdf);
|
||||
openpgl::cpp::SetScatteringWeight(state->guiding.path_segment, guiding_vec3f(weight_rgb));
|
||||
openpgl::cpp::SetIsDelta(state->guiding.path_segment, is_delta);
|
||||
openpgl::cpp::SetEta(state->guiding.path_segment, eta);
|
||||
openpgl::cpp::SetRoughness(state->guiding.path_segment, min_roughness);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the emission at the current surface intersection (physical or virtual) */
|
||||
ccl_device_forceinline void guiding_record_surface_emission(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const Spectrum Le,
|
||||
const float mis_weight)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
const float3 Le_rgb = spectrum_to_rgb(Le);
|
||||
|
||||
openpgl::cpp::SetDirectContribution(state->guiding.path_segment, guiding_vec3f(Le_rgb));
|
||||
openpgl::cpp::SetMiWeight(state->guiding.path_segment, mis_weight);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Record BSSRDF Interactions */
|
||||
|
||||
/* Records/Adds a new path segment where the vertex position is the point of entry
|
||||
* of the sub surface scattering boundary.
|
||||
* If the path is not terminated this call is usually followed by a call of
|
||||
* guiding_record_bssrdf_weight and guiding_record_bssrdf_bounce. */
|
||||
ccl_device_forceinline void guiding_record_bssrdf_segment(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 P,
|
||||
const float3 I)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
const pgl_vec3f zero = guiding_vec3f(zero_float3());
|
||||
const pgl_vec3f one = guiding_vec3f(one_float3());
|
||||
|
||||
state->guiding.path_segment = kg->opgl_path_segment_storage->NextSegment();
|
||||
openpgl::cpp::SetPosition(state->guiding.path_segment, guiding_point3f(P));
|
||||
openpgl::cpp::SetDirectionOut(state->guiding.path_segment, guiding_vec3f(I));
|
||||
openpgl::cpp::SetVolumeScatter(state->guiding.path_segment, true);
|
||||
openpgl::cpp::SetScatteredContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetDirectContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, one);
|
||||
openpgl::cpp::SetEta(state->guiding.path_segment, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the transmission of the path at the point of entry while passing
|
||||
* the surface boundary.*/
|
||||
ccl_device_forceinline void guiding_record_bssrdf_weight(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const Spectrum weight,
|
||||
const Spectrum albedo)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Note albedo left out here, will be included in guiding_record_bssrdf_bounce. */
|
||||
const float3 weight_rgb = spectrum_to_rgb(safe_divide_color(weight, albedo));
|
||||
|
||||
kernel_assert(state->guiding.path_segment != nullptr);
|
||||
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, guiding_vec3f(zero_float3()));
|
||||
openpgl::cpp::SetScatteringWeight(state->guiding.path_segment, guiding_vec3f(weight_rgb));
|
||||
openpgl::cpp::SetIsDelta(state->guiding.path_segment, false);
|
||||
openpgl::cpp::SetEta(state->guiding.path_segment, 1.0f);
|
||||
openpgl::cpp::SetRoughness(state->guiding.path_segment, 1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the direction at the point of entry the path takes when sampling the SSS contribution.
|
||||
* If not terminated this function is usually followed by a call of
|
||||
* guiding_record_volume_transmission to record the transmittance between the point of entry and
|
||||
* the point of exit.*/
|
||||
ccl_device_forceinline void guiding_record_bssrdf_bounce(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float pdf,
|
||||
const float3 N,
|
||||
const float3 omega_in,
|
||||
const Spectrum weight,
|
||||
const Spectrum albedo)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
const float3 normal = clamp(N, -one_float3(), one_float3());
|
||||
const float3 weight_rgb = spectrum_to_rgb(weight * albedo);
|
||||
|
||||
kernel_assert(state->guiding.path_segment != nullptr);
|
||||
|
||||
openpgl::cpp::SetVolumeScatter(state->guiding.path_segment, false);
|
||||
openpgl::cpp::SetNormal(state->guiding.path_segment, guiding_vec3f(normal));
|
||||
openpgl::cpp::SetDirectionIn(state->guiding.path_segment, guiding_vec3f(omega_in));
|
||||
openpgl::cpp::SetPDFDirectionIn(state->guiding.path_segment, pdf);
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, guiding_vec3f(weight_rgb));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Record Volume Interactions */
|
||||
|
||||
/* Records/Adds a new path segment with the current path vertex being inside a volume.
|
||||
* If the path is not terminated this call is usually followed by a call of
|
||||
* guiding_record_volume_bounce. */
|
||||
ccl_device_forceinline void guiding_record_volume_segment(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 P,
|
||||
const float3 I)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
const pgl_vec3f zero = guiding_vec3f(zero_float3());
|
||||
const pgl_vec3f one = guiding_vec3f(one_float3());
|
||||
|
||||
state->guiding.path_segment = kg->opgl_path_segment_storage->NextSegment();
|
||||
|
||||
openpgl::cpp::SetPosition(state->guiding.path_segment, guiding_point3f(P));
|
||||
openpgl::cpp::SetDirectionOut(state->guiding.path_segment, guiding_vec3f(I));
|
||||
openpgl::cpp::SetVolumeScatter(state->guiding.path_segment, true);
|
||||
openpgl::cpp::SetScatteredContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetDirectContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, one);
|
||||
openpgl::cpp::SetEta(state->guiding.path_segment, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the volume scattering event at the current vertex position of the segment.*/
|
||||
ccl_device_forceinline void guiding_record_volume_bounce(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private const ShaderData *sd,
|
||||
const Spectrum weight,
|
||||
const float pdf,
|
||||
const float3 omega_in,
|
||||
const float roughness)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
const float3 weight_rgb = spectrum_to_rgb(weight);
|
||||
const float3 normal = make_float3(0.0f, 0.0f, 1.0f);
|
||||
|
||||
kernel_assert(state->guiding.path_segment != nullptr);
|
||||
|
||||
openpgl::cpp::SetVolumeScatter(state->guiding.path_segment, true);
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, guiding_vec3f(one_float3()));
|
||||
openpgl::cpp::SetNormal(state->guiding.path_segment, guiding_vec3f(normal));
|
||||
openpgl::cpp::SetDirectionIn(state->guiding.path_segment, guiding_vec3f(omega_in));
|
||||
openpgl::cpp::SetPDFDirectionIn(state->guiding.path_segment, pdf);
|
||||
openpgl::cpp::SetScatteringWeight(state->guiding.path_segment, guiding_vec3f(weight_rgb));
|
||||
openpgl::cpp::SetIsDelta(state->guiding.path_segment, false);
|
||||
openpgl::cpp::SetEta(state->guiding.path_segment, 1.f);
|
||||
openpgl::cpp::SetRoughness(state->guiding.path_segment, roughness);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the transmission (a.k.a. transmittance weight) between the current path segment
|
||||
* and the next one, when the path is inside or passes a volume.*/
|
||||
ccl_device_forceinline void guiding_record_volume_transmission(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 transmittance_weight)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->guiding.path_segment) {
|
||||
// TODO (sherholz): need to find a better way to avoid this check
|
||||
if ((transmittance_weight[0] < 0.f || !std::isfinite(transmittance_weight[0]) ||
|
||||
std::isnan(transmittance_weight[0])) ||
|
||||
(transmittance_weight[1] < 0.f || !std::isfinite(transmittance_weight[1]) ||
|
||||
std::isnan(transmittance_weight[1])) ||
|
||||
(transmittance_weight[2] < 0.f || !std::isfinite(transmittance_weight[2]) ||
|
||||
std::isnan(transmittance_weight[2]))) {
|
||||
}
|
||||
else {
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment,
|
||||
guiding_vec3f(transmittance_weight));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the emission of a volume at the vertex of the current path segment. */
|
||||
ccl_device_forceinline void guiding_record_volume_emission(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const Spectrum Le)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->guiding.path_segment) {
|
||||
const float3 Le_rgb = spectrum_to_rgb(Le);
|
||||
|
||||
openpgl::cpp::SetDirectContribution(state->guiding.path_segment, guiding_vec3f(Le_rgb));
|
||||
openpgl::cpp::SetMiWeight(state->guiding.path_segment, 1.0f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Record Light Interactions */
|
||||
|
||||
/* Adds a pseudo path vertex/segment when intersecting a virtual light source.
|
||||
* (e.g., area, sphere, or disk light). This call is often followed
|
||||
* a call of guiding_record_surface_emission, if the intersected light source
|
||||
* emits light in the direction of the path. */
|
||||
ccl_device_forceinline void guiding_record_light_surface_segment(
|
||||
KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
const pgl_vec3f zero = guiding_vec3f(zero_float3());
|
||||
const pgl_vec3f one = guiding_vec3f(one_float3());
|
||||
const float3 ray_P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float3 ray_D = INTEGRATOR_STATE(state, ray, D);
|
||||
const float3 P = ray_P + isect->t * ray_D;
|
||||
|
||||
state->guiding.path_segment = kg->opgl_path_segment_storage->NextSegment();
|
||||
openpgl::cpp::SetPosition(state->guiding.path_segment, guiding_point3f(P));
|
||||
openpgl::cpp::SetDirectionOut(state->guiding.path_segment, guiding_vec3f(-ray_D));
|
||||
openpgl::cpp::SetNormal(state->guiding.path_segment, guiding_vec3f(-ray_D));
|
||||
openpgl::cpp::SetDirectionIn(state->guiding.path_segment, guiding_vec3f(ray_D));
|
||||
openpgl::cpp::SetPDFDirectionIn(state->guiding.path_segment, 1.0f);
|
||||
openpgl::cpp::SetVolumeScatter(state->guiding.path_segment, false);
|
||||
openpgl::cpp::SetScatteredContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetDirectContribution(state->guiding.path_segment, zero);
|
||||
openpgl::cpp::SetTransmittanceWeight(state->guiding.path_segment, one);
|
||||
openpgl::cpp::SetScatteringWeight(state->guiding.path_segment, one);
|
||||
openpgl::cpp::SetEta(state->guiding.path_segment, 1.0f);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records/Adds a final path segment when the path leaves the scene and
|
||||
* intersects with a background light (e.g., background color,
|
||||
* distant light, or env map). The vertex for this segment is placed along
|
||||
* the current ray far out the scene.*/
|
||||
ccl_device_forceinline void guiding_record_background(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const Spectrum L,
|
||||
const float mis_weight)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float3 L_rgb = spectrum_to_rgb(L);
|
||||
const float3 ray_P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float3 ray_D = INTEGRATOR_STATE(state, ray, D);
|
||||
const float3 P = ray_P + (1e6f) * ray_D;
|
||||
const float3 normal = make_float3(0.0f, 0.0f, 1.0f);
|
||||
|
||||
openpgl::cpp::PathSegment background_segment;
|
||||
openpgl::cpp::SetPosition(&background_segment, guiding_vec3f(P));
|
||||
openpgl::cpp::SetNormal(&background_segment, guiding_vec3f(normal));
|
||||
openpgl::cpp::SetDirectionOut(&background_segment, guiding_vec3f(-ray_D));
|
||||
openpgl::cpp::SetDirectContribution(&background_segment, guiding_vec3f(L_rgb));
|
||||
openpgl::cpp::SetMiWeight(&background_segment, mis_weight);
|
||||
kg->opgl_path_segment_storage->AddSegment(background_segment);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Records the scattered contribution of a next event estimation
|
||||
* (i.e., a direct light estimate scattered at the current path vertex
|
||||
* towards the previous vertex).*/
|
||||
ccl_device_forceinline void guiding_record_direct_light(KernelGlobals kg,
|
||||
IntegratorShadowState state)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
if (state->shadow_path.path_segment) {
|
||||
const Spectrum Lo = safe_divide_color(INTEGRATOR_STATE(state, shadow_path, throughput),
|
||||
INTEGRATOR_STATE(state, shadow_path, unlit_throughput));
|
||||
|
||||
const float3 Lo_rgb = spectrum_to_rgb(Lo);
|
||||
openpgl::cpp::AddScatteredContribution(state->shadow_path.path_segment, guiding_vec3f(Lo_rgb));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Record Russian Roulette */
|
||||
/* Records the probability of continuing the path at the current path segment. */
|
||||
ccl_device_forceinline void guiding_record_continuation_probability(
|
||||
KernelGlobals kg, IntegratorState state, const float continuation_probability)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->guiding.path_segment) {
|
||||
openpgl::cpp::SetRussianRouletteProbability(state->guiding.path_segment,
|
||||
continuation_probability);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Path guiding debug render passes. */
|
||||
|
||||
/* Write a set of path guiding related debug information (e.g., guiding probability at first
|
||||
* bounce) into separate rendering passes.*/
|
||||
ccl_device_forceinline void guiding_write_debug_passes(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_global float *ccl_restrict
|
||||
render_buffer)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
# ifdef WITH_CYCLES_DEBUG
|
||||
if (!kernel_data.integrator.train_guiding) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (INTEGRATOR_STATE(state, path, bounce) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t render_pixel_index = INTEGRATOR_STATE(state, path, render_pixel_index);
|
||||
const uint64_t render_buffer_offset = (uint64_t)render_pixel_index *
|
||||
kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + render_buffer_offset;
|
||||
|
||||
if (kernel_data.film.pass_guiding_probability != PASS_UNUSED) {
|
||||
float guiding_prob = state->guiding.surface_guiding_sampling_prob;
|
||||
film_write_pass_float(buffer + kernel_data.film.pass_guiding_probability, guiding_prob);
|
||||
}
|
||||
|
||||
if (kernel_data.film.pass_guiding_avg_roughness != PASS_UNUSED) {
|
||||
float avg_roughness = 0.0f;
|
||||
float sum_sample_weight = 0.0f;
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
ccl_private const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if (!CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
|
||||
continue;
|
||||
}
|
||||
avg_roughness += sc->sample_weight * bsdf_get_specular_roughness_squared(sc);
|
||||
sum_sample_weight += sc->sample_weight;
|
||||
}
|
||||
|
||||
avg_roughness = avg_roughness > 0.f ? avg_roughness / sum_sample_weight : 0.f;
|
||||
|
||||
film_write_pass_float(buffer + kernel_data.film.pass_guiding_avg_roughness, avg_roughness);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Guided BSDFs */
|
||||
|
||||
ccl_device_forceinline bool guiding_bsdf_init(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 P,
|
||||
const float3 N,
|
||||
ccl_private float &rand)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (kg->opgl_surface_sampling_distribution->Init(
|
||||
kg->opgl_guiding_field, guiding_point3f(P), rand, true)) {
|
||||
kg->opgl_surface_sampling_distribution->ApplyCosineProduct(guiding_point3f(N));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float guiding_bsdf_sample(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float2 rand_bsdf,
|
||||
ccl_private float3 *omega_in)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
pgl_vec3f wo;
|
||||
const pgl_point2f rand = openpgl::cpp::Point2(rand_bsdf.x, rand_bsdf.y);
|
||||
const float pdf = kg->opgl_surface_sampling_distribution->SamplePDF(rand, wo);
|
||||
*omega_in = make_float3(wo.x, wo.y, wo.z);
|
||||
return pdf;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device_forceinline float guiding_bsdf_pdf(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 omega_in)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
return kg->opgl_surface_sampling_distribution->PDF(guiding_vec3f(omega_in));
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Guided Volume Phases */
|
||||
|
||||
ccl_device_forceinline bool guiding_phase_init(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 P,
|
||||
const float3 D,
|
||||
const float g,
|
||||
ccl_private float &rand)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (kg->opgl_volume_sampling_distribution->Init(
|
||||
kg->opgl_guiding_field, guiding_point3f(P), rand, true)) {
|
||||
kg->opgl_volume_sampling_distribution->ApplySingleLobeHenyeyGreensteinProduct(guiding_vec3f(D),
|
||||
g);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ccl_device_forceinline float guiding_phase_sample(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float2 rand_phase,
|
||||
ccl_private float3 *omega_in)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
pgl_vec3f wo;
|
||||
const pgl_point2f rand = openpgl::cpp::Point2(rand_phase.x, rand_phase.y);
|
||||
const float pdf = kg->opgl_volume_sampling_distribution->SamplePDF(rand, wo);
|
||||
*omega_in = make_float3(wo.x, wo.y, wo.z);
|
||||
return pdf;
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
ccl_device_forceinline float guiding_phase_pdf(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
const float3 omega_in)
|
||||
{
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
return kg->opgl_volume_sampling_distribution->PDF(guiding_vec3f(omega_in));
|
||||
#else
|
||||
return 0.0f;
|
||||
#endif
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "kernel/film/light_passes.h"
|
||||
|
||||
#include "kernel/integrator/guiding.h"
|
||||
#include "kernel/integrator/path_state.h"
|
||||
#include "kernel/integrator/shadow_catcher.h"
|
||||
|
||||
@@ -48,13 +49,15 @@ ccl_device_forceinline bool integrator_intersect_terminate(KernelGlobals kg,
|
||||
* surfaces in front of emission do we need to evaluate the shader, since we
|
||||
* perform MIS as part of indirect rays. */
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
const float probability = path_state_continuation_probability(kg, state, path_flag);
|
||||
INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = probability;
|
||||
const float continuation_probability = path_state_continuation_probability(kg, state, path_flag);
|
||||
INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = continuation_probability;
|
||||
|
||||
if (probability != 1.0f) {
|
||||
guiding_record_continuation_probability(kg, state, continuation_probability);
|
||||
|
||||
if (continuation_probability != 1.0f) {
|
||||
const float terminate = path_state_rng_1D(kg, &rng_state, PRNG_TERMINATE);
|
||||
|
||||
if (probability == 0.0f || terminate >= probability) {
|
||||
if (continuation_probability == 0.0f || terminate >= continuation_probability) {
|
||||
if (shader_flags & SD_HAS_EMISSION) {
|
||||
/* Mark path to be terminated right after shader evaluation on the surface. */
|
||||
INTEGRATOR_STATE_WRITE(state, path, flag) |= PATH_RAY_TERMINATE_ON_NEXT_SURFACE;
|
||||
|
@@ -807,7 +807,7 @@ ccl_device_forceinline bool mnee_path_contribution(KernelGlobals kg,
|
||||
float3 wo = normalize_len(vertices[0].p - sd->P, &wo_len);
|
||||
|
||||
/* Initialize throughput and evaluate receiver bsdf * |n.wo|. */
|
||||
surface_shader_bsdf_eval(kg, sd, wo, false, throughput, ls->shader);
|
||||
surface_shader_bsdf_eval(kg, state, sd, wo, throughput, ls->shader);
|
||||
|
||||
/* Update light sample with new position / direct.ion
|
||||
* and keep pdf in vertex area measure */
|
||||
|
@@ -56,6 +56,11 @@ ccl_device_inline void path_state_init_integrator(KernelGlobals kg,
|
||||
INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = 1.0f;
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = one_spectrum();
|
||||
|
||||
#ifdef __PATH_GUIDING__
|
||||
INTEGRATOR_STATE_WRITE(state, path, unguided_throughput) = 1.0f;
|
||||
INTEGRATOR_STATE_WRITE(state, guiding, path_segment) = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef __MNEE__
|
||||
INTEGRATOR_STATE_WRITE(state, path, mnee) = 0;
|
||||
#endif
|
||||
@@ -249,7 +254,11 @@ ccl_device_inline float path_state_continuation_probability(KernelGlobals kg,
|
||||
|
||||
/* Probabilistic termination: use sqrt() to roughly match typical view
|
||||
* transform and do path termination a bit later on average. */
|
||||
return min(sqrtf(reduce_max(fabs(INTEGRATOR_STATE(state, path, throughput)))), 1.0f);
|
||||
Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
throughput *= INTEGRATOR_STATE(state, path, unguided_throughput);
|
||||
#endif
|
||||
return min(sqrtf(reduce_max(fabs(throughput))), 1.0f);
|
||||
}
|
||||
|
||||
ccl_device_inline bool path_state_ao_bounce(KernelGlobals kg, ConstIntegratorState state)
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "kernel/film/light_passes.h"
|
||||
|
||||
#include "kernel/integrator/guiding.h"
|
||||
#include "kernel/integrator/surface_shader.h"
|
||||
|
||||
#include "kernel/light/light.h"
|
||||
@@ -124,6 +125,7 @@ ccl_device_inline void integrate_background(KernelGlobals kg,
|
||||
mis_weight = light_sample_mis_weight_forward(kg, mis_ray_pdf, pdf);
|
||||
}
|
||||
|
||||
guiding_record_background(kg, state, L, mis_weight);
|
||||
L *= mis_weight;
|
||||
}
|
||||
|
||||
@@ -185,6 +187,7 @@ ccl_device_inline void integrate_distant_lights(KernelGlobals kg,
|
||||
}
|
||||
|
||||
/* Write to render buffer. */
|
||||
guiding_record_background(kg, state, light_eval, mis_weight);
|
||||
film_write_surface_emission(
|
||||
kg, state, light_eval, mis_weight, render_buffer, kernel_data.background.lightgroup);
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
|
||||
Intersection isect ccl_optional_struct_init;
|
||||
integrator_state_read_isect(kg, state, &isect);
|
||||
|
||||
guiding_record_light_surface_segment(kg, state, &isect);
|
||||
|
||||
float3 ray_P = INTEGRATOR_STATE(state, ray, P);
|
||||
const float3 ray_D = INTEGRATOR_STATE(state, ray, D);
|
||||
const float ray_time = INTEGRATOR_STATE(state, ray, time);
|
||||
@@ -66,6 +68,7 @@ ccl_device_inline void integrate_light(KernelGlobals kg,
|
||||
}
|
||||
|
||||
/* Write to render buffer. */
|
||||
guiding_record_surface_emission(kg, state, light_eval, mis_weight);
|
||||
film_write_surface_emission(kg, state, light_eval, mis_weight, render_buffer, ls.group);
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kernel/integrator/guiding.h"
|
||||
#include "kernel/integrator/shade_volume.h"
|
||||
#include "kernel/integrator/surface_shader.h"
|
||||
#include "kernel/integrator/volume_stack.h"
|
||||
@@ -165,6 +166,7 @@ ccl_device void integrator_shade_shadow(KernelGlobals kg,
|
||||
return;
|
||||
}
|
||||
else {
|
||||
guiding_record_direct_light(kg, state);
|
||||
film_write_direct_light(kg, state, render_buffer);
|
||||
integrator_shadow_path_terminate(kg, state, DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW);
|
||||
return;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "kernel/integrator/mnee.h"
|
||||
|
||||
#include "kernel/integrator/guiding.h"
|
||||
#include "kernel/integrator/path_state.h"
|
||||
#include "kernel/integrator/subsurface.h"
|
||||
#include "kernel/integrator/surface_shader.h"
|
||||
@@ -101,7 +102,7 @@ ccl_device_forceinline bool integrate_surface_holdout(KernelGlobals kg,
|
||||
}
|
||||
|
||||
ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
|
||||
ConstIntegratorState state,
|
||||
IntegratorState state,
|
||||
ccl_private const ShaderData *sd,
|
||||
ccl_global float *ccl_restrict
|
||||
render_buffer)
|
||||
@@ -128,6 +129,7 @@ ccl_device_forceinline void integrate_surface_emission(KernelGlobals kg,
|
||||
mis_weight = light_sample_mis_weight_forward(kg, bsdf_pdf, pdf);
|
||||
}
|
||||
|
||||
guiding_record_surface_emission(kg, state, L, mis_weight);
|
||||
film_write_surface_emission(
|
||||
kg, state, L, mis_weight, render_buffer, object_lightgroup(kg, sd->object));
|
||||
}
|
||||
@@ -171,7 +173,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
|
||||
Ray ray ccl_optional_struct_init;
|
||||
BsdfEval bsdf_eval ccl_optional_struct_init;
|
||||
const bool is_transmission = surface_shader_is_transmission(sd, ls.D);
|
||||
|
||||
const bool is_transmission = dot(ls.D, sd->N) < 0.0f;
|
||||
|
||||
#ifdef __MNEE__
|
||||
int mnee_vertex_count = 0;
|
||||
@@ -182,13 +185,15 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
const bool use_caustics = kernel_data_fetch(lights, ls.lamp).use_caustics;
|
||||
if (use_caustics) {
|
||||
/* Are we on a caustic caster? */
|
||||
if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER))
|
||||
if (is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_CASTER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Are we on a caustic receiver? */
|
||||
if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER))
|
||||
if (!is_transmission && (sd->object_flag & SD_OBJECT_CAUSTICS_RECEIVER)) {
|
||||
mnee_vertex_count = kernel_path_mnee_sample(
|
||||
kg, state, sd, emission_sd, rng_state, &ls, &bsdf_eval);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,8 +212,7 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
}
|
||||
|
||||
/* Evaluate BSDF. */
|
||||
const float bsdf_pdf = surface_shader_bsdf_eval(
|
||||
kg, sd, ls.D, is_transmission, &bsdf_eval, ls.shader);
|
||||
const float bsdf_pdf = surface_shader_bsdf_eval(kg, state, sd, ls.D, &bsdf_eval, ls.shader);
|
||||
bsdf_eval_mul(&bsdf_eval, light_eval / ls.pdf);
|
||||
|
||||
if (ls.shader & SHADER_USE_MIS) {
|
||||
@@ -256,8 +260,8 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
/* Copy state from main path to shadow path. */
|
||||
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput) *
|
||||
bsdf_eval_sum(&bsdf_eval);
|
||||
const Spectrum unlit_throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput = unlit_throughput * bsdf_eval_sum(&bsdf_eval);
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
PackedSpectrum pass_diffuse_weight;
|
||||
@@ -327,6 +331,11 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
||||
shadow_state, shadow_path, lightgroup) = (ls.type != LIGHT_BACKGROUND) ?
|
||||
ls.group + 1 :
|
||||
kernel_data.background.lightgroup + 1;
|
||||
#ifdef __PATH_GUIDING__
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unlit_throughput) = unlit_throughput;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, path_segment) = INTEGRATOR_STATE(
|
||||
state, guiding, path_segment);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Path tracing: bounce off or through surface with new direction. */
|
||||
@@ -352,16 +361,52 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
||||
#endif
|
||||
|
||||
/* BSDF closure, sample direction. */
|
||||
float bsdf_pdf;
|
||||
float bsdf_pdf = 0.0f, unguided_bsdf_pdf = 0.0f;
|
||||
BsdfEval bsdf_eval ccl_optional_struct_init;
|
||||
float3 bsdf_omega_in ccl_optional_struct_init;
|
||||
int label;
|
||||
|
||||
label = surface_shader_bsdf_sample_closure(
|
||||
kg, sd, sc, rand_bsdf, &bsdf_eval, &bsdf_omega_in, &bsdf_pdf);
|
||||
float2 bsdf_sampled_roughness = make_float2(1.0f, 1.0f);
|
||||
float bsdf_eta = 1.0f;
|
||||
|
||||
if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) {
|
||||
return LABEL_NONE;
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (kernel_data.integrator.use_surface_guiding) {
|
||||
label = surface_shader_bsdf_guided_sample_closure(kg,
|
||||
state,
|
||||
sd,
|
||||
sc,
|
||||
rand_bsdf,
|
||||
&bsdf_eval,
|
||||
&bsdf_omega_in,
|
||||
&bsdf_pdf,
|
||||
&unguided_bsdf_pdf,
|
||||
&bsdf_sampled_roughness,
|
||||
&bsdf_eta);
|
||||
|
||||
if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) {
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(state, path, unguided_throughput) *= bsdf_pdf / unguided_bsdf_pdf;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
label = surface_shader_bsdf_sample_closure(kg,
|
||||
sd,
|
||||
sc,
|
||||
rand_bsdf,
|
||||
&bsdf_eval,
|
||||
&bsdf_omega_in,
|
||||
&bsdf_pdf,
|
||||
&bsdf_sampled_roughness,
|
||||
&bsdf_eta);
|
||||
|
||||
if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) {
|
||||
return LABEL_NONE;
|
||||
}
|
||||
|
||||
unguided_bsdf_pdf = bsdf_pdf;
|
||||
}
|
||||
|
||||
if (label & LABEL_TRANSPARENT) {
|
||||
@@ -381,9 +426,8 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
||||
}
|
||||
|
||||
/* Update throughput. */
|
||||
Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
throughput *= bsdf_eval_sum(&bsdf_eval) / bsdf_pdf;
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput;
|
||||
const Spectrum bsdf_weight = bsdf_eval_sum(&bsdf_eval) / bsdf_pdf;
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) *= bsdf_weight;
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
if (INTEGRATOR_STATE(state, path, bounce) == 0) {
|
||||
@@ -398,10 +442,21 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
||||
if (!(label & LABEL_TRANSPARENT)) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = bsdf_pdf;
|
||||
INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = fminf(
|
||||
bsdf_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
|
||||
unguided_bsdf_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
|
||||
}
|
||||
|
||||
path_state_next(kg, state, label);
|
||||
|
||||
guiding_record_surface_bounce(kg,
|
||||
state,
|
||||
sd,
|
||||
bsdf_weight,
|
||||
bsdf_pdf,
|
||||
sd->N,
|
||||
normalize(bsdf_omega_in),
|
||||
bsdf_sampled_roughness,
|
||||
bsdf_eta);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
@@ -423,14 +478,15 @@ ccl_device_forceinline int integrate_surface_volume_only_bounce(IntegratorState
|
||||
ccl_device_forceinline bool integrate_surface_terminate(IntegratorState state,
|
||||
const uint32_t path_flag)
|
||||
{
|
||||
const float probability = (path_flag & PATH_RAY_TERMINATE_ON_NEXT_SURFACE) ?
|
||||
0.0f :
|
||||
INTEGRATOR_STATE(state, path, continuation_probability);
|
||||
if (probability == 0.0f) {
|
||||
const float continuation_probability = (path_flag & PATH_RAY_TERMINATE_ON_NEXT_SURFACE) ?
|
||||
0.0f :
|
||||
INTEGRATOR_STATE(
|
||||
state, path, continuation_probability);
|
||||
if (continuation_probability == 0.0f) {
|
||||
return true;
|
||||
}
|
||||
else if (probability != 1.0f) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) /= probability;
|
||||
else if (continuation_probability != 1.0f) {
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) /= continuation_probability;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -538,6 +594,8 @@ ccl_device bool integrate_surface(KernelGlobals kg,
|
||||
#ifdef __VOLUME__
|
||||
if (!(sd.flag & SD_HAS_ONLY_VOLUME)) {
|
||||
#endif
|
||||
guiding_record_surface_segment(kg, state, &sd);
|
||||
|
||||
#ifdef __SUBSURFACE__
|
||||
/* Can skip shader evaluation for BSSRDF exit point without bump mapping. */
|
||||
if (!(path_flag & PATH_RAY_SUBSURFACE) || ((sd.flag & SD_HAS_BSSRDF_BUMP)))
|
||||
@@ -603,6 +661,10 @@ ccl_device bool integrate_surface(KernelGlobals kg,
|
||||
RNGState rng_state;
|
||||
path_state_rng_load(state, &rng_state);
|
||||
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
surface_shader_prepare_guiding(kg, state, &sd, &rng_state);
|
||||
guiding_write_debug_passes(kg, state, &sd, render_buffer);
|
||||
#endif
|
||||
/* Direct light. */
|
||||
PROFILING_EVENT(PROFILING_SHADE_SURFACE_DIRECT_LIGHT);
|
||||
integrate_surface_direct_light<node_feature_mask>(kg, state, &sd, &rng_state);
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#include "kernel/film/denoising_passes.h"
|
||||
#include "kernel/film/light_passes.h"
|
||||
|
||||
#include "kernel/integrator/guiding.h"
|
||||
#include "kernel/integrator/intersect_closest.h"
|
||||
#include "kernel/integrator/path_state.h"
|
||||
#include "kernel/integrator/volume_shader.h"
|
||||
@@ -612,6 +613,7 @@ ccl_device_forceinline void volume_integrate_heterogeneous(
|
||||
const Spectrum emission = volume_emission_integrate(
|
||||
&coeff, closure_flag, transmittance, dt);
|
||||
accum_emission += result.indirect_throughput * emission;
|
||||
guiding_record_volume_emission(kg, state, emission);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,7 +763,7 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
||||
|
||||
/* Evaluate BSDF. */
|
||||
BsdfEval phase_eval ccl_optional_struct_init;
|
||||
const float phase_pdf = volume_shader_phase_eval(kg, sd, phases, ls->D, &phase_eval);
|
||||
float phase_pdf = volume_shader_phase_eval(kg, state, sd, phases, ls->D, &phase_eval);
|
||||
|
||||
if (ls->shader & SHADER_USE_MIS) {
|
||||
float mis_weight = light_sample_mis_weight_nee(kg, ls->pdf, phase_pdf);
|
||||
@@ -848,6 +850,12 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
||||
ls->group + 1 :
|
||||
kernel_data.background.lightgroup + 1;
|
||||
|
||||
# ifdef __PATH_GUIDING__
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, unlit_throughput) = throughput;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, path_segment) = INTEGRATOR_STATE(
|
||||
state, guiding, path_segment);
|
||||
# endif
|
||||
|
||||
integrator_state_copy_volume_stack_to_shadow(kg, shadow_state, state);
|
||||
}
|
||||
|
||||
@@ -861,18 +869,54 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
||||
{
|
||||
PROFILING_INIT(kg, PROFILING_SHADE_VOLUME_INDIRECT_LIGHT);
|
||||
|
||||
const float2 rand_phase = path_state_rng_2D(kg, rng_state, PRNG_VOLUME_PHASE);
|
||||
float2 rand_phase = path_state_rng_2D(kg, rng_state, PRNG_VOLUME_PHASE);
|
||||
|
||||
ccl_private const ShaderVolumeClosure *svc = volume_shader_phase_pick(phases, &rand_phase);
|
||||
|
||||
/* Phase closure, sample direction. */
|
||||
float phase_pdf;
|
||||
float phase_pdf = 0.0f, unguided_phase_pdf = 0.0f;
|
||||
BsdfEval phase_eval ccl_optional_struct_init;
|
||||
float3 phase_omega_in ccl_optional_struct_init;
|
||||
float sampled_roughness = 1.0f;
|
||||
int label;
|
||||
|
||||
const int label = volume_shader_phase_sample(
|
||||
kg, sd, phases, rand_phase, &phase_eval, &phase_omega_in, &phase_pdf);
|
||||
# if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (kernel_data.integrator.use_guiding) {
|
||||
label = volume_shader_phase_guided_sample(kg,
|
||||
state,
|
||||
sd,
|
||||
svc,
|
||||
rand_phase,
|
||||
&phase_eval,
|
||||
&phase_omega_in,
|
||||
&phase_pdf,
|
||||
&unguided_phase_pdf,
|
||||
&sampled_roughness);
|
||||
|
||||
if (phase_pdf == 0.0f || bsdf_eval_is_zero(&phase_eval)) {
|
||||
return false;
|
||||
if (phase_pdf == 0.0f || bsdf_eval_is_zero(&phase_eval)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(state, path, unguided_throughput) *= phase_pdf / unguided_phase_pdf;
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{
|
||||
label = volume_shader_phase_sample(kg,
|
||||
sd,
|
||||
phases,
|
||||
svc,
|
||||
rand_phase,
|
||||
&phase_eval,
|
||||
&phase_omega_in,
|
||||
&phase_pdf,
|
||||
&sampled_roughness);
|
||||
|
||||
if (phase_pdf == 0.0f || bsdf_eval_is_zero(&phase_eval)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unguided_phase_pdf = phase_pdf;
|
||||
}
|
||||
|
||||
/* Setup ray. */
|
||||
@@ -887,9 +931,15 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
||||
INTEGRATOR_STATE_WRITE(state, isect, prim) = sd->prim;
|
||||
INTEGRATOR_STATE_WRITE(state, isect, object) = sd->object;
|
||||
|
||||
const Spectrum phase_weight = bsdf_eval_sum(&phase_eval) / phase_pdf;
|
||||
|
||||
/* Add phase function sampling data to the path segment. */
|
||||
guiding_record_volume_bounce(
|
||||
kg, state, sd, phase_weight, phase_pdf, normalize(phase_omega_in), sampled_roughness);
|
||||
|
||||
/* Update throughput. */
|
||||
const Spectrum throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
const Spectrum throughput_phase = throughput * bsdf_eval_sum(&phase_eval) / phase_pdf;
|
||||
const Spectrum throughput_phase = throughput * phase_weight;
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = throughput_phase;
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
@@ -900,7 +950,7 @@ ccl_device_forceinline bool integrate_volume_phase_scatter(
|
||||
/* Update path state */
|
||||
INTEGRATOR_STATE_WRITE(state, path, mis_ray_pdf) = phase_pdf;
|
||||
INTEGRATOR_STATE_WRITE(state, path, min_ray_pdf) = fminf(
|
||||
phase_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
|
||||
unguided_phase_pdf, INTEGRATOR_STATE(state, path, min_ray_pdf));
|
||||
|
||||
path_state_next(kg, state, label);
|
||||
return true;
|
||||
@@ -939,6 +989,10 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
|
||||
VOLUME_READ_LAMBDA(integrator_state_read_volume_stack(state, i))
|
||||
const float step_size = volume_stack_step_size(kg, volume_read_lambda_pass);
|
||||
|
||||
# if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
const float3 initial_throughput = INTEGRATOR_STATE(state, path, throughput);
|
||||
# endif
|
||||
|
||||
/* TODO: expensive to zero closures? */
|
||||
VolumeIntegrateResult result = {};
|
||||
volume_integrate_heterogeneous(kg,
|
||||
@@ -956,17 +1010,50 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
|
||||
* to be terminated. That will shading evaluating to leave out any scattering closures,
|
||||
* but emission and absorption are still handled for multiple importance sampling. */
|
||||
const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
const float probability = (path_flag & PATH_RAY_TERMINATE_IN_NEXT_VOLUME) ?
|
||||
0.0f :
|
||||
INTEGRATOR_STATE(state, path, continuation_probability);
|
||||
if (probability == 0.0f) {
|
||||
const float continuation_probability = (path_flag & PATH_RAY_TERMINATE_IN_NEXT_VOLUME) ?
|
||||
0.0f :
|
||||
INTEGRATOR_STATE(
|
||||
state, path, continuation_probability);
|
||||
if (continuation_probability == 0.0f) {
|
||||
return VOLUME_PATH_MISSED;
|
||||
}
|
||||
|
||||
# if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
bool guiding_generated_new_segment = false;
|
||||
if (kernel_data.integrator.use_guiding) {
|
||||
/* Record transmittance using change in throughput. */
|
||||
float3 transmittance_weight = spectrum_to_rgb(
|
||||
safe_divide_color(result.indirect_throughput, initial_throughput));
|
||||
guiding_record_volume_transmission(kg, state, transmittance_weight);
|
||||
|
||||
if (result.indirect_scatter) {
|
||||
const float3 P = ray->P + result.indirect_t * ray->D;
|
||||
|
||||
/* Record volume segment up to direct scatter position.
|
||||
* TODO: volume segment is wrong when direct_t and indirect_t. */
|
||||
if (result.direct_scatter && (result.direct_t == result.indirect_t)) {
|
||||
guiding_record_volume_segment(kg, state, P, sd.I);
|
||||
guiding_generated_new_segment = true;
|
||||
}
|
||||
|
||||
# if PATH_GUIDING_LEVEL >= 4
|
||||
/* TODO: this position will be wrong for direct light pdf computation,
|
||||
* since the direct light position may be different? */
|
||||
volume_shader_prepare_guiding(
|
||||
kg, state, &sd, &rng_state, P, ray->D, &result.direct_phases, direct_sample_method);
|
||||
# endif
|
||||
}
|
||||
else {
|
||||
/* No guiding if we don't scatter. */
|
||||
state->guiding.use_volume_guiding = false;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Direct light. */
|
||||
if (result.direct_scatter) {
|
||||
const float3 direct_P = ray->P + result.direct_t * ray->D;
|
||||
result.direct_throughput /= probability;
|
||||
result.direct_throughput /= continuation_probability;
|
||||
integrate_volume_direct_light(kg,
|
||||
state,
|
||||
&sd,
|
||||
@@ -979,16 +1066,22 @@ ccl_device VolumeIntegrateEvent volume_integrate(KernelGlobals kg,
|
||||
|
||||
/* Indirect light.
|
||||
*
|
||||
* Only divide throughput by probability if we scatter. For the attenuation
|
||||
* Only divide throughput by continuation_probability if we scatter. For the attenuation
|
||||
* case the next surface will already do this division. */
|
||||
if (result.indirect_scatter) {
|
||||
result.indirect_throughput /= probability;
|
||||
result.indirect_throughput /= continuation_probability;
|
||||
}
|
||||
INTEGRATOR_STATE_WRITE(state, path, throughput) = result.indirect_throughput;
|
||||
|
||||
if (result.indirect_scatter) {
|
||||
sd.P = ray->P + result.indirect_t * ray->D;
|
||||
|
||||
# if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 1
|
||||
if (!guiding_generated_new_segment) {
|
||||
guiding_record_volume_segment(kg, state, sd.P, sd.I);
|
||||
}
|
||||
# endif
|
||||
|
||||
if (integrate_volume_phase_scatter(kg, state, &sd, &rng_state, &result.indirect_phases)) {
|
||||
return VOLUME_PATH_SCATTERED;
|
||||
}
|
||||
|
@@ -40,6 +40,16 @@ KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, pass_glossy_weight, KERNEL_FEA
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, uint16_t, num_hits, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Light group. */
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, uint8_t, lightgroup, KERNEL_FEATURE_PATH_TRACING)
|
||||
/* Path guiding. */
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, PackedSpectrum, unlit_throughput, KERNEL_FEATURE_PATH_GUIDING)
|
||||
#ifdef __PATH_GUIDING__
|
||||
KERNEL_STRUCT_MEMBER(shadow_path,
|
||||
openpgl::cpp::PathSegment *,
|
||||
path_segment,
|
||||
KERNEL_FEATURE_PATH_GUIDING)
|
||||
#else
|
||||
KERNEL_STRUCT_MEMBER(shadow_path, uint64_t, path_segment, KERNEL_FEATURE_PATH_GUIDING)
|
||||
#endif
|
||||
KERNEL_STRUCT_END(shadow_path)
|
||||
|
||||
/********************************** Shadow Ray *******************************/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user