Mesh: Replace auto smooth with node group #108014
|
@ -6,15 +6,24 @@
|
|||
set(EMBREE_EXTRA_ARGS
|
||||
-DEMBREE_ISPC_SUPPORT=OFF
|
||||
-DEMBREE_TUTORIALS=OFF
|
||||
-DEMBREE_STATIC_LIB=ON
|
||||
-DEMBREE_STATIC_LIB=OFF
|
||||
-DEMBREE_RAY_MASK=ON
|
||||
-DEMBREE_FILTER_FUNCTION=ON
|
||||
-DEMBREE_BACKFACE_CULLING=OFF
|
||||
-DEMBREE_BACKFACE_CULLING_CURVES=ON
|
||||
-DEMBREE_BACKFACE_CULLING_SPHERES=ON
|
||||
-DEMBREE_TASKING_SYSTEM=TBB
|
||||
-DEMBREE_TBB_ROOT=${LIBDIR}/tbb
|
||||
-DTBB_ROOT=${LIBDIR}/tbb
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(EMBREE_EXTRA_ARGS
|
||||
${EMBREE_EXTRA_ARGS}
|
||||
-DCMAKE_DEBUG_POSTFIX=_d
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT BLENDER_PLATFORM_ARM)
|
||||
set(EMBREE_EXTRA_ARGS
|
||||
${EMBREE_EXTRA_ARGS}
|
||||
|
@ -45,25 +54,19 @@ add_dependencies(
|
|||
)
|
||||
|
||||
if(WIN32)
|
||||
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_embree after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree ${HARVEST_TARGET}/embree
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree/include ${HARVEST_TARGET}/embree/include
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree/lib ${HARVEST_TARGET}/embree/lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/embree/share ${HARVEST_TARGET}/embree/share
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/bin/embree4.dll ${HARVEST_TARGET}/embree/bin/embree4.dll
|
||||
DEPENDEES install
|
||||
)
|
||||
else()
|
||||
ExternalProject_Add_Step(external_embree after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree3.lib ${HARVEST_TARGET}/embree/lib/embree3_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree_avx.lib ${HARVEST_TARGET}/embree/lib/embree_avx_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree_avx2.lib ${HARVEST_TARGET}/embree/lib/embree_avx2_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree_sse42.lib ${HARVEST_TARGET}/embree/lib/embree_sse42_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/lexers.lib ${HARVEST_TARGET}/embree/lib/lexers_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/math.lib ${HARVEST_TARGET}/embree/lib/math_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/simd.lib ${HARVEST_TARGET}/embree/lib/simd_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/sys.lib ${HARVEST_TARGET}/embree/lib/sys_d.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/tasking.lib ${HARVEST_TARGET}/embree/lib/tasking_d.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add_Step(external_embree after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/bin/embree4_d.dll ${HARVEST_TARGET}/embree/bin/embree4_d.dll
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/embree/lib/embree4_d.lib ${HARVEST_TARGET}/embree/lib/embree4_d.lib
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
|
|
@ -218,6 +218,7 @@ else()
|
|||
harvest(openimagedenoise/lib openimagedenoise/lib "*.a")
|
||||
harvest(embree/include embree/include "*.h")
|
||||
harvest(embree/lib embree/lib "*.a")
|
||||
harvest(embree/lib embree/lib "*${SHAREDLIBEXT}*")
|
||||
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")
|
||||
|
|
|
@ -478,9 +478,9 @@ set(SQLITE_HASH_TYPE SHA1)
|
|||
set(SQLITE_FILE sqlite-autoconf-${SQLLITE_LONG_VERSION}.tar.gz)
|
||||
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
|
||||
|
||||
set(EMBREE_VERSION 3.13.4)
|
||||
set(EMBREE_VERSION 4.0.1)
|
||||
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
|
||||
set(EMBREE_HASH 52d0be294d6c88ba7a6c9e046796e7be)
|
||||
set(EMBREE_HASH dd26617719a587e126b341d1b32f7fd0)
|
||||
set(EMBREE_HASH_TYPE MD5)
|
||||
set(EMBREE_FILE embree-v${EMBREE_VERSION}.zip)
|
||||
|
||||
|
@ -534,10 +534,10 @@ set(WL_PROTOCOLS_URI https://gitlab.freedesktop.org/wayland/wayland-protocols/-/
|
|||
set(WL_PROTOCOLS_HASH a28ff59a56e2ebb746048b6ef8d931d6)
|
||||
set(WL_PROTOCOLS_HASH_TYPE MD5)
|
||||
|
||||
set(WAYLAND_VERSION 1.21.0)
|
||||
set(WAYLAND_VERSION 1.22.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_URI https://gitlab.freedesktop.org/wayland/wayland/-/releases/${WAYLAND_VERSION}/downloads/wayland-${WAYLAND_VERSION}.tar.xz)
|
||||
set(WAYLAND_HASH 7410ab549e3928fce9381455b17b0803)
|
||||
set(WAYLAND_HASH_TYPE MD5)
|
||||
|
||||
set(WAYLAND_LIBDECOR_VERSION 0.1.0)
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
diff -Naur org/kernels/rtcore_config.h.in embree-3.13.4/kernels/rtcore_config.h.in
|
||||
--- org/kernels/rtcore_config.h.in 2022-06-14 22:13:52 -0600
|
||||
+++ embree-3.13.4/kernels/rtcore_config.h.in 2022-06-24 15:20:12 -0600
|
||||
@@ -14,6 +14,7 @@
|
||||
#cmakedefine01 EMBREE_MIN_WIDTH
|
||||
#define RTC_MIN_WIDTH EMBREE_MIN_WIDTH
|
||||
|
||||
+#cmakedefine EMBREE_STATIC_LIB
|
||||
#cmakedefine EMBREE_API_NAMESPACE
|
||||
|
||||
#if defined(EMBREE_API_NAMESPACE)
|
||||
diff --git a/kernels/CMakeLists.txt b/kernels/CMakeLists.txt
|
||||
index 7c2f43d..106b1d5 100644
|
||||
--- a/kernels/CMakeLists.txt
|
||||
+++ b/kernels/CMakeLists.txt
|
||||
@@ -201,6 +201,12 @@ embree_files(EMBREE_LIBRARY_FILES_AVX512 ${AVX512})
|
||||
@@ -208,6 +208,12 @@ embree_files(EMBREE_LIBRARY_FILES_AVX512 ${AVX512})
|
||||
#message("AVX2: ${EMBREE_LIBRARY_FILES_AVX2}")
|
||||
#message("AVX512: ${EMBREE_LIBRARY_FILES_AVX512}")
|
||||
|
||||
|
@ -26,7 +15,7 @@ index 7c2f43d..106b1d5 100644
|
|||
# replaces all .cpp files with a dummy file that includes that .cpp file
|
||||
# this is to work around an ICC name mangling issue related to lambda functions under windows
|
||||
MACRO (CreateISADummyFiles list isa)
|
||||
@@ -277,7 +283,7 @@ IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX)
|
||||
@@ -311,7 +317,7 @@ IF (EMBREE_ISA_AVX AND EMBREE_LIBRARY_FILES_AVX)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
|
@ -35,3 +24,128 @@ index 7c2f43d..106b1d5 100644
|
|||
DISABLE_STACK_PROTECTOR_FOR_INTERSECTORS(${EMBREE_LIBRARY_FILES_AVX2})
|
||||
ADD_LIBRARY(embree_avx2 STATIC ${EMBREE_LIBRARY_FILES_AVX2})
|
||||
TARGET_LINK_LIBRARIES(embree_avx2 PRIVATE tasking)
|
||||
diff --git a/include/embree4/rtcore_device.h b/include/embree4/rtcore_device.h
|
||||
index 45bf95583..62ee7787d 100644
|
||||
--- a/include/embree4/rtcore_device.h
|
||||
+++ b/include/embree4/rtcore_device.h
|
||||
@@ -55,6 +55,7 @@ enum RTCDeviceProperty
|
||||
RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED = 66,
|
||||
RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED = 67,
|
||||
RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED = 68,
|
||||
+ RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED = 69,
|
||||
|
||||
RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED = 96,
|
||||
RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED = 97,
|
||||
diff --git a/kernels/common/device.cpp b/kernels/common/device.cpp
|
||||
index 3ffac7e37..215ccc961 100644
|
||||
--- a/kernels/common/device.cpp
|
||||
+++ b/kernels/common/device.cpp
|
||||
@@ -170,6 +170,9 @@ namespace embree
|
||||
#if defined (EMBREE_BACKFACE_CULLING_CURVES)
|
||||
v += "backfacecullingcurves ";
|
||||
#endif
|
||||
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ v += "backfacecullingspheres ";
|
||||
+#endif
|
||||
#if defined(EMBREE_FILTER_FUNCTION)
|
||||
v += "intersection_filter ";
|
||||
#endif
|
||||
@@ -477,6 +480,12 @@ namespace embree
|
||||
case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_CURVES_ENABLED: return 0;
|
||||
#endif
|
||||
|
||||
+#if defined(EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 1;
|
||||
+#else
|
||||
+ case RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: return 0;
|
||||
+#endif
|
||||
+
|
||||
#if defined(EMBREE_COMPACT_POLYS)
|
||||
case RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: return 1;
|
||||
#else
|
||||
diff --git a/kernels/config.h.in b/kernels/config.h.in
|
||||
index f02c90360..ba9acde56 100644
|
||||
--- a/kernels/config.h.in
|
||||
+++ b/kernels/config.h.in
|
||||
@@ -5,6 +5,7 @@
|
||||
#cmakedefine EMBREE_STAT_COUNTERS
|
||||
#cmakedefine EMBREE_BACKFACE_CULLING
|
||||
#cmakedefine EMBREE_BACKFACE_CULLING_CURVES
|
||||
+#cmakedefine EMBREE_BACKFACE_CULLING_SPHERES
|
||||
#cmakedefine EMBREE_FILTER_FUNCTION
|
||||
#cmakedefine EMBREE_IGNORE_INVALID_RAYS
|
||||
#cmakedefine EMBREE_GEOMETRY_TRIANGLE
|
||||
diff --git a/kernels/geometry/sphere_intersector.h b/kernels/geometry/sphere_intersector.h
|
||||
index 074f910a2..30f490818 100644
|
||||
--- a/kernels/geometry/sphere_intersector.h
|
||||
+++ b/kernels/geometry/sphere_intersector.h
|
||||
@@ -106,8 +106,13 @@ namespace embree
|
||||
const vbool<M> valid_front = valid & (ray.tnear() <= t_front) & (t_front <= ray.tfar);
|
||||
const vbool<M> valid_back = valid & (ray.tnear() <= t_back ) & (t_back <= ray.tfar);
|
||||
|
||||
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ /* check if there is a first hit */
|
||||
+ const vbool<M> valid_first = valid_front;
|
||||
+#else
|
||||
/* check if there is a first hit */
|
||||
const vbool<M> valid_first = valid_front | valid_back;
|
||||
+#endif
|
||||
if (unlikely(none(valid_first)))
|
||||
return false;
|
||||
|
||||
@@ -120,7 +125,8 @@ namespace embree
|
||||
|
||||
/* invoke intersection filter for first hit */
|
||||
const bool is_hit_first = epilog(valid_first, hit);
|
||||
-
|
||||
+
|
||||
+#if !defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
/* check for possible second hits before potentially accepted hit */
|
||||
const vfloat<M> t_second = t_back;
|
||||
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar);
|
||||
@@ -131,7 +137,9 @@ namespace embree
|
||||
const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
|
||||
hit = SphereIntersectorHitM<M> (t_second, Ng_second);
|
||||
const bool is_hit_second = epilog(valid_second, hit);
|
||||
-
|
||||
+#else
|
||||
+ constexpr bool is_hit_second = false;
|
||||
+#endif
|
||||
return is_hit_first | is_hit_second;
|
||||
}
|
||||
|
||||
@@ -186,8 +194,13 @@ namespace embree
|
||||
const vbool<M> valid_front = valid & (ray.tnear()[k] <= t_front) & (t_front <= ray.tfar[k]);
|
||||
const vbool<M> valid_back = valid & (ray.tnear()[k] <= t_back ) & (t_back <= ray.tfar[k]);
|
||||
|
||||
+#if defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
+ /* check if there is a first hit */
|
||||
+ const vbool<M> valid_first = valid_front;
|
||||
+#else
|
||||
/* check if there is a first hit */
|
||||
const vbool<M> valid_first = valid_front | valid_back;
|
||||
+#endif
|
||||
if (unlikely(none(valid_first)))
|
||||
return false;
|
||||
|
||||
@@ -200,7 +213,8 @@ namespace embree
|
||||
|
||||
/* invoke intersection filter for first hit */
|
||||
const bool is_hit_first = epilog(valid_first, hit);
|
||||
-
|
||||
+
|
||||
+#if !defined (EMBREE_BACKFACE_CULLING_SPHERES)
|
||||
/* check for possible second hits before potentially accepted hit */
|
||||
const vfloat<M> t_second = t_back;
|
||||
const vbool<M> valid_second = valid_front & valid_back & (t_second <= ray.tfar[k]);
|
||||
@@ -211,7 +225,9 @@ namespace embree
|
||||
const Vec3vf<M> Ng_second = td_back * ray_dir - perp;
|
||||
hit = SphereIntersectorHitM<M> (t_second, Ng_second);
|
||||
const bool is_hit_second = epilog(valid_second, hit);
|
||||
-
|
||||
+#else
|
||||
+ constexpr bool is_hit_second = false;
|
||||
+#endif
|
||||
return is_hit_first | is_hit_second;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ SET(_embree_SEARCH_DIRS
|
|||
|
||||
FIND_PATH(EMBREE_INCLUDE_DIR
|
||||
NAMES
|
||||
embree4/rtcore.h
|
||||
embree3/rtcore.h
|
||||
HINTS
|
||||
${_embree_SEARCH_DIRS}
|
||||
|
@ -30,28 +31,67 @@ FIND_PATH(EMBREE_INCLUDE_DIR
|
|||
include
|
||||
)
|
||||
|
||||
IF(NOT (("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") OR (APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))))
|
||||
SET(_embree_SIMD_COMPONENTS
|
||||
embree_sse42
|
||||
embree_avx
|
||||
embree_avx2
|
||||
)
|
||||
IF(EXISTS ${EMBREE_INCLUDE_DIR}/embree4/rtcore_config.h)
|
||||
SET(EMBREE_MAJOR_VERSION 4)
|
||||
ELSE()
|
||||
SET(EMBREE_MAJOR_VERSION 3)
|
||||
ENDIF()
|
||||
|
||||
SET(_embree_FIND_COMPONENTS
|
||||
embree3
|
||||
${_embree_SIMD_COMPONENTS}
|
||||
lexers
|
||||
math
|
||||
simd
|
||||
sys
|
||||
tasking
|
||||
)
|
||||
IF(EMBREE_INCLUDE_DIR)
|
||||
FILE(READ ${EMBREE_INCLUDE_DIR}/embree${EMBREE_MAJOR_VERSION}/rtcore_config.h _embree_config_header)
|
||||
IF(_embree_config_header MATCHES "#define EMBREE_STATIC_LIB")
|
||||
SET(EMBREE_STATIC_LIB TRUE)
|
||||
ELSE()
|
||||
SET(EMBREE_STATIC_LIB FALSE)
|
||||
ENDIF()
|
||||
IF(_embree_config_header MATCHES "#define EMBREE_SYCL_SUPPORT")
|
||||
SET(EMBREE_SYCL_SUPPORT TRUE)
|
||||
ELSE()
|
||||
SET(EMBREE_SYCL_SUPPORT FALSE)
|
||||
ENDIF()
|
||||
UNSET(_embree_config_header)
|
||||
ENDIF()
|
||||
|
||||
IF(EMBREE_STATIC_LIB)
|
||||
IF(NOT (("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") OR (APPLE AND ("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64"))))
|
||||
SET(_embree_SIMD_COMPONENTS
|
||||
embree_sse42
|
||||
embree_avx
|
||||
embree_avx2
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(EMBREE_SYCL_SUPPORT)
|
||||
SET(_embree_GPU_COMPONENTS
|
||||
embree4_sycl
|
||||
embree_rthwif
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
SET(_embree_FIND_COMPONENTS
|
||||
embree${EMBREE_MAJOR_VERSION}
|
||||
${_embree_SIMD_COMPONENTS}
|
||||
${_embree_GPU_COMPONENTS}
|
||||
lexers
|
||||
math
|
||||
simd
|
||||
sys
|
||||
tasking
|
||||
)
|
||||
ELSE()
|
||||
SET(_embree_FIND_COMPONENTS
|
||||
embree${EMBREE_MAJOR_VERSION}
|
||||
)
|
||||
IF(EMBREE_SYCL_SUPPORT)
|
||||
LIST(APPEND _embree_FIND_COMPONENTS
|
||||
embree4_sycl
|
||||
)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
SET(_embree_LIBRARIES)
|
||||
FOREACH(COMPONENT ${_embree_FIND_COMPONENTS})
|
||||
STRING(TOUPPER ${COMPONENT} UPPERCOMPONENT)
|
||||
|
||||
FIND_LIBRARY(EMBREE_${UPPERCOMPONENT}_LIBRARY
|
||||
NAMES
|
||||
${COMPONENT}
|
||||
|
@ -60,18 +100,9 @@ FOREACH(COMPONENT ${_embree_FIND_COMPONENTS})
|
|||
PATH_SUFFIXES
|
||||
lib64 lib
|
||||
)
|
||||
IF(NOT EMBREE_${UPPERCOMPONENT}_LIBRARY)
|
||||
IF(EMBREE_EMBREE3_LIBRARY)
|
||||
# If we can't find all the static libraries, try to fall back to the shared library if found.
|
||||
# This allows building with a shared embree library
|
||||
SET(_embree_LIBRARIES ${EMBREE_EMBREE3_LIBRARY})
|
||||
BREAK()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
LIST(APPEND _embree_LIBRARIES "${EMBREE_${UPPERCOMPONENT}_LIBRARY}")
|
||||
ENDFOREACH()
|
||||
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set EMBREE_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
|
@ -85,6 +116,9 @@ ENDIF()
|
|||
|
||||
MARK_AS_ADVANCED(
|
||||
EMBREE_INCLUDE_DIR
|
||||
EMBREE_MAJOR_VERSION
|
||||
EMBREE_SYCL_SUPPORT
|
||||
EMBREE_STATIC_LIB
|
||||
)
|
||||
|
||||
FOREACH(COMPONENT ${_embree_FIND_COMPONENTS})
|
||||
|
|
|
@ -108,6 +108,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(SYCL
|
|||
|
||||
IF(SYCL_FOUND)
|
||||
SET(SYCL_INCLUDE_DIR ${SYCL_INCLUDE_DIR} ${SYCL_INCLUDE_DIR}/sycl)
|
||||
SET(SYCL_LIBRARIES ${SYCL_LIBRARY})
|
||||
ELSE()
|
||||
SET(SYCL_SYCL_FOUND FALSE)
|
||||
ENDIF()
|
||||
|
|
|
@ -330,6 +330,7 @@ if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
|||
endforeach()
|
||||
set(EMBREE_LIBRARIES ${_embree_libraries_force_load})
|
||||
endif()
|
||||
add_bundled_libraries(embree/lib)
|
||||
|
||||
if(WITH_OPENIMAGEDENOISE)
|
||||
find_package(OpenImageDenoise REQUIRED)
|
||||
|
|
|
@ -317,7 +317,7 @@ if(WITH_CYCLES AND WITH_CYCLES_OSL)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
|
||||
if(WITH_CYCLES AND (WITH_CYCLES_DEVICE_ONEAPI OR (WITH_CYCLES_EMBREE AND EMBREE_SYCL_SUPPORT)))
|
||||
set(CYCLES_LEVEL_ZERO ${LIBDIR}/level-zero CACHE PATH "Path to Level Zero installation")
|
||||
if(EXISTS ${CYCLES_LEVEL_ZERO} AND NOT LEVEL_ZERO_ROOT_DIR)
|
||||
set(LEVEL_ZERO_ROOT_DIR ${CYCLES_LEVEL_ZERO})
|
||||
|
@ -453,6 +453,7 @@ add_bundled_libraries(opencolorio/lib)
|
|||
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
||||
find_package(Embree 3.8.0 REQUIRED)
|
||||
endif()
|
||||
add_bundled_libraries(embree/lib)
|
||||
|
||||
if(WITH_OPENIMAGEDENOISE)
|
||||
find_package_wrapper(OpenImageDenoise)
|
||||
|
|
|
@ -850,27 +850,75 @@ endif()
|
|||
if(WITH_CYCLES AND WITH_CYCLES_EMBREE)
|
||||
windows_find_package(Embree)
|
||||
if(NOT Embree_FOUND)
|
||||
set(EMBREE_ROOT_DIR ${LIBDIR}/embree)
|
||||
set(EMBREE_INCLUDE_DIRS ${LIBDIR}/embree/include)
|
||||
set(EMBREE_LIBRARIES
|
||||
optimized ${LIBDIR}/embree/lib/embree3.lib
|
||||
optimized ${LIBDIR}/embree/lib/embree_avx2.lib
|
||||
optimized ${LIBDIR}/embree/lib/embree_avx.lib
|
||||
optimized ${LIBDIR}/embree/lib/embree_sse42.lib
|
||||
optimized ${LIBDIR}/embree/lib/lexers.lib
|
||||
optimized ${LIBDIR}/embree/lib/math.lib
|
||||
optimized ${LIBDIR}/embree/lib/simd.lib
|
||||
optimized ${LIBDIR}/embree/lib/sys.lib
|
||||
optimized ${LIBDIR}/embree/lib/tasking.lib
|
||||
|
||||
debug ${LIBDIR}/embree/lib/embree3_d.lib
|
||||
debug ${LIBDIR}/embree/lib/embree_avx2_d.lib
|
||||
debug ${LIBDIR}/embree/lib/embree_avx_d.lib
|
||||
debug ${LIBDIR}/embree/lib/embree_sse42_d.lib
|
||||
debug ${LIBDIR}/embree/lib/lexers_d.lib
|
||||
debug ${LIBDIR}/embree/lib/math_d.lib
|
||||
debug ${LIBDIR}/embree/lib/simd_d.lib
|
||||
debug ${LIBDIR}/embree/lib/sys_d.lib
|
||||
debug ${LIBDIR}/embree/lib/tasking_d.lib
|
||||
if(EXISTS ${LIBDIR}/embree/include/embree4/rtcore_config.h)
|
||||
set(EMBREE_MAJOR_VERSION 4)
|
||||
else()
|
||||
set(EMBREE_MAJOR_VERSION 3)
|
||||
endif()
|
||||
|
||||
file(READ ${LIBDIR}/embree/include/embree${EMBREE_MAJOR_VERSION}/rtcore_config.h _embree_config_header)
|
||||
if(_embree_config_header MATCHES "#define EMBREE_STATIC_LIB")
|
||||
set(EMBREE_STATIC_LIB TRUE)
|
||||
else()
|
||||
set(EMBREE_STATIC_LIB FALSE)
|
||||
endif()
|
||||
|
||||
if(_embree_config_header MATCHES "#define EMBREE_SYCL_SUPPORT")
|
||||
set(EMBREE_SYCL_SUPPORT TRUE)
|
||||
else()
|
||||
set(EMBREE_SYCL_SUPPORT FALSE)
|
||||
endif()
|
||||
|
||||
set(EMBREE_LIBRARIES
|
||||
optimized ${LIBDIR}/embree/lib/embree${EMBREE_MAJOR_VERSION}.lib
|
||||
debug ${LIBDIR}/embree/lib/embree${EMBREE_MAJOR_VERSION}_d.lib
|
||||
)
|
||||
|
||||
if(EMBREE_SYCL_SUPPORT)
|
||||
set(EMBREE_LIBRARIES
|
||||
${EMBREE_LIBRARIES}
|
||||
optimized ${LIBDIR}/embree/lib/embree4_sycl.lib
|
||||
debug ${LIBDIR}/embree/lib/embree4_sycl_d.lib
|
||||
)
|
||||
endif()
|
||||
|
||||
if(EMBREE_STATIC_LIB)
|
||||
set(EMBREE_LIBRARIES
|
||||
${EMBREE_LIBRARIES}
|
||||
optimized ${LIBDIR}/embree/lib/embree_avx2.lib
|
||||
optimized ${LIBDIR}/embree/lib/embree_avx.lib
|
||||
optimized ${LIBDIR}/embree/lib/embree_sse42.lib
|
||||
optimized ${LIBDIR}/embree/lib/lexers.lib
|
||||
optimized ${LIBDIR}/embree/lib/math.lib
|
||||
optimized ${LIBDIR}/embree/lib/simd.lib
|
||||
optimized ${LIBDIR}/embree/lib/sys.lib
|
||||
optimized ${LIBDIR}/embree/lib/tasking.lib
|
||||
debug ${LIBDIR}/embree/lib/embree_avx2_d.lib
|
||||
debug ${LIBDIR}/embree/lib/embree_avx_d.lib
|
||||
debug ${LIBDIR}/embree/lib/embree_sse42_d.lib
|
||||
debug ${LIBDIR}/embree/lib/lexers_d.lib
|
||||
debug ${LIBDIR}/embree/lib/math_d.lib
|
||||
debug ${LIBDIR}/embree/lib/simd_d.lib
|
||||
debug ${LIBDIR}/embree/lib/sys_d.lib
|
||||
debug ${LIBDIR}/embree/lib/tasking_d.lib
|
||||
)
|
||||
|
||||
if(EMBREE_SYCL_SUPPORT)
|
||||
set(EMBREE_LIBRARIES
|
||||
${EMBREE_LIBRARIES}
|
||||
optimized ${LIBDIR}/embree/lib/embree_rthwif.lib
|
||||
debug ${LIBDIR}/embree/lib/embree_rthwif_d.lib
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(NOT EMBREE_STATIC_LIB)
|
||||
list(APPEND PLATFORM_BUNDLED_LIBRARIES
|
||||
RELEASE ${EMBREE_ROOT_DIR}/bin/embree${EMBREE_MAJOR_VERSION}.dll
|
||||
DEBUG ${EMBREE_ROOT_DIR}/bin/embree${EMBREE_MAJOR_VERSION}_d.dll
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -1029,7 +1077,7 @@ endif()
|
|||
set(ZSTD_INCLUDE_DIRS ${LIBDIR}/zstd/include)
|
||||
set(ZSTD_LIBRARIES ${LIBDIR}/zstd/lib/zstd_static.lib)
|
||||
|
||||
if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
|
||||
if(WITH_CYCLES AND (WITH_CYCLES_DEVICE_ONEAPI OR (WITH_CYCLES_EMBREE AND EMBREE_SYCL_SUPPORT)))
|
||||
set(LEVEL_ZERO_ROOT_DIR ${LIBDIR}/level_zero)
|
||||
set(CYCLES_SYCL ${LIBDIR}/dpcpp CACHE PATH "Path to oneAPI DPC++ compiler")
|
||||
if(EXISTS ${CYCLES_SYCL} AND NOT SYCL_ROOT_DIR)
|
||||
|
@ -1040,7 +1088,7 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
|
|||
${SYCL_ROOT_DIR}/bin/sycl[0-9].dll
|
||||
)
|
||||
foreach(sycl_runtime_library IN LISTS _sycl_runtime_libraries_glob)
|
||||
string(REPLACE ".dll" "_d.dll" sycl_runtime_library_debug ${sycl_runtime_library})
|
||||
string(REPLACE ".dll" "d.dll" sycl_runtime_library_debug ${sycl_runtime_library})
|
||||
list(APPEND _sycl_runtime_libraries RELEASE ${sycl_runtime_library})
|
||||
list(APPEND _sycl_runtime_libraries DEBUG ${sycl_runtime_library_debug})
|
||||
endforeach()
|
||||
|
@ -1055,6 +1103,8 @@ if(WITH_CYCLES AND WITH_CYCLES_DEVICE_ONEAPI)
|
|||
|
||||
list(APPEND PLATFORM_BUNDLED_LIBRARIES ${_sycl_runtime_libraries})
|
||||
unset(_sycl_runtime_libraries)
|
||||
|
||||
set(SYCL_LIBRARIES optimized ${SYCL_LIBRARY} debug ${SYCL_LIBRARY_DEBUG})
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -112,6 +112,7 @@ def create_manifest(
|
|||
print(f'Building manifest of files: "{outpath}"...', end="", flush=True)
|
||||
with outpath.open("w", encoding="utf-8") as outfile:
|
||||
main_files_to_manifest(blender_srcdir, outfile)
|
||||
assets_to_manifest(blender_srcdir, outfile)
|
||||
submodules_to_manifest(blender_srcdir, version, outfile)
|
||||
|
||||
if packages_dir:
|
||||
|
@ -140,6 +141,18 @@ def submodules_to_manifest(
|
|||
print(path, file=outfile)
|
||||
|
||||
|
||||
def assets_to_manifest(blender_srcdir: Path, outfile: TextIO) -> None:
|
||||
assert not blender_srcdir.is_absolute()
|
||||
|
||||
assets_dir = blender_srcdir.parent / "lib" / "assets"
|
||||
for path in assets_dir.glob("*"):
|
||||
if path.name == "working":
|
||||
continue
|
||||
if path.name in SKIP_NAMES:
|
||||
continue
|
||||
print(path, file=outfile)
|
||||
|
||||
|
||||
def packages_to_manifest(outfile: TextIO, packages_dir: Path) -> None:
|
||||
for path in packages_dir.glob("*"):
|
||||
if not path.is_file():
|
||||
|
@ -170,7 +183,9 @@ def create_tarball(
|
|||
command += [
|
||||
"--transform",
|
||||
f"s,^{blender_srcdir.name}/,blender-{version}/,g",
|
||||
"--use-compress-program=xz -9",
|
||||
"--transform",
|
||||
f"s,^lib/assets/,blender-{version}/release/datafiles/assets/,g",
|
||||
"--use-compress-program=xz -1",
|
||||
"--create",
|
||||
f"--file={tarball}",
|
||||
f"--files-from={manifest}",
|
||||
|
|
|
@ -1853,8 +1853,6 @@ def pyrna2sphinx(basepath):
|
|||
fw(" %s\n\n" % operator_description)
|
||||
for prop in op.args:
|
||||
write_param(" ", fw, prop)
|
||||
if op.args:
|
||||
fw("\n")
|
||||
|
||||
location = op.get_location()
|
||||
if location != (None, None):
|
||||
|
@ -1865,9 +1863,12 @@ def pyrna2sphinx(basepath):
|
|||
else:
|
||||
url_base = API_BASEURL
|
||||
|
||||
fw(" :file:`%s\\:%d <%s/%s#L%d>`_\n\n" %
|
||||
fw(" :File: `%s\\:%d <%s/%s#L%d>`__\n\n" %
|
||||
(location[0], location[1], url_base, location[0], location[1]))
|
||||
|
||||
if op.args:
|
||||
fw("\n")
|
||||
|
||||
file.close()
|
||||
|
||||
if "bpy.ops" not in EXCLUDE_MODULES:
|
||||
|
|
|
@ -14,3 +14,13 @@ The first three of them were employed by the Blender Foundation during that time
|
|||
Some features (random sounds, dynamic music, playback manager, convolution and HRTFs support) were added as part of the VALS (Virtual Alliances for Learning Society) project by
|
||||
|
||||
- Juan Francisco Crespo Galán <dethon_5@outlook.com>
|
||||
|
||||
The Equalizer sound effect has been added by
|
||||
|
||||
- Marcos Perez
|
||||
|
||||
Several people provided fixes:
|
||||
|
||||
- Aaron Carlisle
|
||||
- Sebastian Parborg
|
||||
- Leon Zandman
|
||||
|
|
|
@ -1,3 +1,104 @@
|
|||
Audaspace 1.4
|
||||
|
||||
- Support for OS specific/native audio devices/backends has been added, that is PulseAudio (Linux), WASAPI (Windows) and CoreAudio (MacOS).
|
||||
- New sound effects have been added, namely Modulator and Equalizer. Thanks to Marcos Perez for contributing the Equalizer.
|
||||
- File stream info: if an audio file contains multiple streams you can choose which one to process instead of taking the first one (this feature is only supported by ffmpeg, not libsndfile).
|
||||
- API Change: double instead of float for time values for more precise timing control.
|
||||
- There have been lots of bugfixes, which are basically the majority of all changes.
|
||||
- And some other minor improvements were implemented as well.
|
||||
|
||||
Detailed list of changes:
|
||||
|
||||
d4042d9 Port changes in Blender to upstream.
|
||||
b60fb45 Equalizer
|
||||
ab04e84 Fixes
|
||||
8f0c305 Fix build error with MSVC 17.4+ ported from Blender.
|
||||
ce44342 Minor documentation update.
|
||||
cdcb3f4 Migrate from distuils to setuptools for python module.
|
||||
21eccef Fix FindFFTW to find the float version fftw3f.
|
||||
ab15e2f Bugfix: API change in new ffmpeg version.
|
||||
a097be8 Clang format file added, valid from now on.
|
||||
2fc9fb7 Porting bugfix from Blender upstream.
|
||||
bb655b7 Bugfix: wrong sample size computation for PulseAudio.
|
||||
a150495 Bugfix: Buffer did not support buffers > 2 GB.
|
||||
034645c Update for ffmpeg 5.
|
||||
932739c Bugfix: WASAPI hangs.
|
||||
4fcd47c WASAPI: fix bug when switching the default device while there is no playback.
|
||||
a16fbd2 Python API: fix to get convolution in the python API.
|
||||
27ac5c1 WASAPI: always switch to default audio device.
|
||||
1b03e6c Bugfix: catch exception if file cannot be read.
|
||||
369ff6e PulseAudio: remove unused underflow callback.
|
||||
2d8bf3a PulseAudio: improve synchronization accuracy.
|
||||
4868e14 Revert PulseAudioDevice back from ThreadedDevice to threaded mainloop.
|
||||
6a04446 Adding a jack style mixing thread with a ring buffer for pulseaudio.
|
||||
5d4b57b Implement RingBuffer class.
|
||||
e02d3aa FFMPEG: fix seeking and duration calculation.
|
||||
07b9fa0 Adding file stream functionality.
|
||||
5a8ad27 Porting changes from Blender.
|
||||
fa47258 Bugfix: PulseAudio writing to little data on request.
|
||||
ca3edb5 PulseAudio: increase buffersize.
|
||||
6d36f3e Pulseaudio: may fix crackling playback start bug.
|
||||
dbeac4b WASAPI: reinitialize device when lost.
|
||||
0cba4d3 Bugfix Pulseaudio: might hang.
|
||||
b73dc6d Bugfix: ffmpeg 4.4 requires channels to be set.
|
||||
f1ecbe0 Fixed typo.
|
||||
09e4f27 Rewrite PulseAudioDevice to use ThreadedDevice.
|
||||
9516924 WASAPI: refactor to simplify and use ThreadedDevice.
|
||||
749c974 Add ThreadedDevice.
|
||||
e68b355 Fix some locks in SoftwareDevice.
|
||||
44b57af Bugfix for deadlock in WASAPIDevice.
|
||||
8c4b266 CMake: fix ERROR to FATAL_ERROR in MESSAGE.
|
||||
5a17338 Rename NullDevice's reported name to None.
|
||||
cd138d7 PulseAudio: add dynamic loading and threading fixes.
|
||||
6e0250f CoreAudio: add CoreAudioClock as synchronizer.
|
||||
43aff35 Fix leakage in CoreAudioDevice.cpp
|
||||
7f6f059 Remove unnecessary cmake code.
|
||||
a5c1a02 Add CoreAudio device for Apple.
|
||||
af96f67 Indentation fix.
|
||||
eec8fd5 WASAPI: use padding also for first buffer submission.
|
||||
c63bd9b WASAPI: deal with IsFormatSupported case.
|
||||
079cccb Hide WITH_PULSEAUDIO when not on Linux.
|
||||
67b5013 Add mingw64 cross compilation toolchain on Linux.
|
||||
a7bfa58 Add WASAPI backend for Windows.
|
||||
be1cb25 Allow AUD_init with nullptr to use default device.
|
||||
fc68868 Compilation fix for mingw.
|
||||
bb79d25 Add a PulseAudio output device.
|
||||
a11f593 Bugfix for unwanted volume fading at the beginning of sounds.
|
||||
8510acf Bugfix: more accurate positioning of sequences.
|
||||
cb816c1 Fix API docs for python playback manager play function
|
||||
d125fa2 Add callback for mixing down audio.
|
||||
789832e Fix numpy import.
|
||||
9a6a802 Bugfix: JOS resampling type bugfix caused integer underflow.
|
||||
ece0842 Fix corrupted document in python bindings
|
||||
28b2ea2 SDL 2: support more audio formats.
|
||||
a39b7e3 Trying to fix Travis CI build for OS X.
|
||||
c924007 Some more changes of times from flaot to double.
|
||||
659afd4 Porting fixes from blender.
|
||||
8e5e2e6 Fix documentation warnings.
|
||||
7a6054f API: All times are now double instead of float.
|
||||
452a724 Mixer sample buffer added channels twice
|
||||
8ddb6c1 Docs: Cleanup Line Wrapping for python examples
|
||||
a0c37b2 Docs: Use class methods for api docs
|
||||
2f8b2e3 Bugfix for invalid offsets provided by ffmpeg's seeking code.
|
||||
20a7a28 Bug fixes for files with more than 8 channels.
|
||||
94dc527 Bugfix: Fading from full volume.
|
||||
2fb9862 Fix: Missing include in FileManager.h.
|
||||
afadb94 Minor CMakeLists.txt formatting fixes.
|
||||
734ef03 Add sample rate parameter to silence generation.
|
||||
ed50f3b Bugfix: Return correct length for modulator and superpose.
|
||||
cb7a314 Adding a modulator sound effect.
|
||||
101c714 Bugfix: don't add non-existing devices to the device manager.
|
||||
7ad99df OpenAL: recreate device if disconnected.
|
||||
a2ff4e8 Bugfix: memory leak in python API.
|
||||
5fb21bb Silence some warnings.
|
||||
9b38605 Some fixes backported from Blender.
|
||||
40a0a34 Udpate for travis.ci.
|
||||
212b4b6 Support newer ffmpeg versions.
|
||||
d27746c Build option: configure whether to build versioned plugins.
|
||||
19c8d9f Make fftw3 optional.
|
||||
aa11968 Bugfix for building with gcc7.
|
||||
10413c5 Fix for seeking with modified pitch.
|
||||
|
||||
Audaspace 1.3
|
||||
=============
|
||||
|
||||
|
@ -10,6 +111,8 @@ Audaspace 1.3
|
|||
- filter python API parameter check
|
||||
- finding ffmpeg with pkgconfig
|
||||
|
||||
Detailed list of changes:
|
||||
|
||||
64884a7 Windows fixes.
|
||||
53ba3e6 Implemented JACK dynamic loading.
|
||||
5ee0ee1 Continues last commit.
|
||||
|
@ -46,6 +149,8 @@ Audaspace 1.2
|
|||
- assuring numpy is installed
|
||||
- building the Python module on Mac OS X with CMake
|
||||
|
||||
Detailed list of changes:
|
||||
|
||||
a6b6e70 Changing default sample rate from 44.1 to 48 kHz.
|
||||
20f0164 Bugfix: CMake custom command for python module on OS X.
|
||||
98679a2 Bugfix: using standard library (s)rand.
|
||||
|
|
|
@ -23,7 +23,7 @@ endif()
|
|||
|
||||
project(audaspace)
|
||||
|
||||
set(AUDASPACE_VERSION 1.3)
|
||||
set(AUDASPACE_VERSION 1.4)
|
||||
set(AUDASPACE_LONG_VERSION ${AUDASPACE_VERSION}.0)
|
||||
|
||||
if(DEFINED AUDASPACE_CMAKE_CFG)
|
||||
|
|
|
@ -15,7 +15,7 @@ Audaspace is written in C++ 11 so a fairly recent compiler (g++ 4.8.2, clang 3.3
|
|||
- Jack (output device)
|
||||
- libsndfile (file access)
|
||||
- ffmpeg (file access)
|
||||
- Python (language binding)
|
||||
- Python (language binding, needs NumPy as well)
|
||||
|
||||
Getting the Code
|
||||
----------------
|
||||
|
|
|
@ -32,7 +32,7 @@ The following (probably incomplete) features are supported by audaspace:
|
|||
License
|
||||
-------
|
||||
|
||||
> Copyright © 2009-2015 Jörg Müller. All rights reserved.
|
||||
> Copyright © 2009-2023 Jörg Müller. All rights reserved.
|
||||
>
|
||||
> Licensed under the Apache License, Version 2.0 (the "License");
|
||||
> you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -165,6 +165,12 @@ AUD_API void AUD_SequenceEntry_move(AUD_SequenceEntry* entry, double begin, doub
|
|||
(*entry)->move(begin, end, skip);
|
||||
}
|
||||
|
||||
AUD_API void AUD_SequenceEntry_setConstantRangeAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame_start, int frame_end, float* data)
|
||||
{
|
||||
AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type));
|
||||
prop->writeConstantRange(data, frame_start, frame_end);
|
||||
}
|
||||
|
||||
AUD_API void AUD_SequenceEntry_setAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated)
|
||||
{
|
||||
AnimateableProperty* prop = (*entry)->getAnimProperty(static_cast<AnimateablePropertyType>(type));
|
||||
|
|
|
@ -68,6 +68,16 @@ extern AUD_API void AUD_Sequence_remove(AUD_Sound* sequence, AUD_SequenceEntry*
|
|||
* Writes animation data to a sequence.
|
||||
* \param sequence The sound scene.
|
||||
* \param type The type of animation data.
|
||||
* \param frame_start Start of the frame range.
|
||||
* \param frame_end End of the frame range.
|
||||
* \param data The data to write.
|
||||
*/
|
||||
AUD_API void AUD_SequenceEntry_setConstantRangeAnimationData(AUD_SequenceEntry* entry, AUD_AnimateablePropertyType type, int frame_start, int frame_end, float* data);
|
||||
|
||||
/**
|
||||
* Writes animation data to a sequenced entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param type The type of animation data.
|
||||
* \param frame The frame this data is for.
|
||||
* \param data The data to write.
|
||||
* \param animated Whether the attribute is animated.
|
||||
|
|
|
@ -112,6 +112,14 @@ public:
|
|||
*/
|
||||
void write(const float* data, int position, int count);
|
||||
|
||||
/**
|
||||
* Fills the properties frame range with constant value and marks it animated.
|
||||
* \param data The new value.
|
||||
* \param position_start The start position in the animation in frames.
|
||||
* \param position_end The end position in the animation in frames.
|
||||
*/
|
||||
void writeConstantRange(const float* data, int position_start, int position_end);
|
||||
|
||||
/**
|
||||
* Reads the properties value.
|
||||
* \param position The position in the animation in frames.
|
||||
|
|
|
@ -198,12 +198,13 @@ public:
|
|||
/**
|
||||
* Adds a new entry to the scene.
|
||||
* \param sound The sound this entry should play.
|
||||
* \param sequence_data Reference to sequence_data. Mainly needed to get the FPS of the scene.
|
||||
* \param begin The start time.
|
||||
* \param end The end time or a negative value if determined by the sound.
|
||||
* \param skip How much seconds should be skipped at the beginning.
|
||||
* \return The entry added.
|
||||
*/
|
||||
std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, double begin, double end, double skip);
|
||||
std::shared_ptr<SequenceEntry> add(std::shared_ptr<ISound> sound, std::shared_ptr<SequenceData> sequence_data, double begin, double end, double skip);
|
||||
|
||||
/**
|
||||
* Removes an entry from the scene.
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "sequence/AnimateableProperty.h"
|
||||
#include "sequence/SequenceData.h"
|
||||
#include "util/ILockable.h"
|
||||
|
||||
#include <mutex>
|
||||
|
@ -63,6 +64,9 @@ private:
|
|||
/// How many seconds are skipped at the beginning.
|
||||
double m_skip;
|
||||
|
||||
/// reference to sequence_data. Mainly needed to get the FPS of the scene.
|
||||
std::shared_ptr<SequenceData> m_sequence_data;
|
||||
|
||||
/// Whether the entry is muted.
|
||||
bool m_muted;
|
||||
|
||||
|
@ -122,9 +126,10 @@ public:
|
|||
* \param begin The start time.
|
||||
* \param end The end time or a negative value if determined by the sound.
|
||||
* \param skip How much seconds should be skipped at the beginning.
|
||||
* \param sequence_data Reference to sequence_data. Mainly needed to get the FPS of the scene.
|
||||
* \param id The ID of the entry.
|
||||
*/
|
||||
SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id);
|
||||
SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, std::shared_ptr<SequenceData> sequence_data, int id);
|
||||
virtual ~SequenceEntry();
|
||||
|
||||
/**
|
||||
|
|
|
@ -65,6 +65,19 @@ void AnimateableProperty::write(const float* data)
|
|||
std::memcpy(getBuffer(), data, m_count * sizeof(float));
|
||||
}
|
||||
|
||||
void AnimateableProperty::writeConstantRange(const float* data, int position_start, int position_end)
|
||||
{
|
||||
assureSize(position_end * m_count * sizeof(float), true);
|
||||
float* buffer = getBuffer();
|
||||
|
||||
for(int i = position_start; i < position_end; i++)
|
||||
{
|
||||
std::memcpy(buffer + i * m_count, data, m_count * sizeof(float));
|
||||
}
|
||||
|
||||
m_isAnimated = true;
|
||||
}
|
||||
|
||||
void AnimateableProperty::write(const float* data, int position, int count)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
|
|
@ -92,7 +92,7 @@ AnimateableProperty* Sequence::getAnimProperty(AnimateablePropertyType type)
|
|||
|
||||
std::shared_ptr<SequenceEntry> Sequence::add(std::shared_ptr<ISound> sound, double begin, double end, double skip)
|
||||
{
|
||||
return m_sequence->add(sound, begin, end, skip);
|
||||
return m_sequence->add(sound, m_sequence, begin, end, skip);
|
||||
}
|
||||
|
||||
void Sequence::remove(std::shared_ptr<SequenceEntry> entry)
|
||||
|
|
|
@ -149,11 +149,11 @@ AnimateableProperty* SequenceData::getAnimProperty(AnimateablePropertyType type)
|
|||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, double begin, double end, double skip)
|
||||
std::shared_ptr<SequenceEntry> SequenceData::add(std::shared_ptr<ISound> sound, std::shared_ptr<SequenceData> sequence_data, double begin, double end, double skip)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
std::shared_ptr<SequenceEntry> entry = std::shared_ptr<SequenceEntry>(new SequenceEntry(sound, begin, end, skip, m_id++));
|
||||
std::shared_ptr<SequenceEntry> entry = std::shared_ptr<SequenceEntry>(new SequenceEntry(sound, begin, end, skip, sequence_data, m_id++));
|
||||
|
||||
m_entries.push_back(entry);
|
||||
m_entry_status++;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, int id) :
|
||||
SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double end, double skip, std::shared_ptr<SequenceData> sequence_data, int id) :
|
||||
m_status(0),
|
||||
m_pos_status(1),
|
||||
m_sound_status(0),
|
||||
|
@ -31,6 +31,7 @@ SequenceEntry::SequenceEntry(std::shared_ptr<ISound> sound, double begin, double
|
|||
m_begin(begin),
|
||||
m_end(end),
|
||||
m_skip(skip),
|
||||
m_sequence_data(sequence_data),
|
||||
m_muted(false),
|
||||
m_relative(true),
|
||||
m_volume_max(1.0f),
|
||||
|
|
|
@ -241,10 +241,38 @@ bool SequenceHandle::seek(double position)
|
|||
return false;
|
||||
|
||||
std::lock_guard<ILockable> lock(*m_entry);
|
||||
double seekpos = position - m_entry->m_begin;
|
||||
if(seekpos < 0)
|
||||
seekpos = 0;
|
||||
seekpos += m_entry->m_skip;
|
||||
|
||||
double seek_frame = (position - m_entry->m_begin) * m_entry->m_sequence_data->getFPS();
|
||||
|
||||
if(seek_frame < 0)
|
||||
seek_frame = 0;
|
||||
|
||||
seek_frame += m_entry->m_skip * m_entry->m_sequence_data->getFPS();
|
||||
|
||||
AnimateableProperty* pitch_property = m_entry->getAnimProperty(AP_PITCH);
|
||||
|
||||
double target_frame = 0;
|
||||
|
||||
if(pitch_property != nullptr)
|
||||
{
|
||||
int frame_start = (m_entry->m_begin - m_entry->m_skip) * m_entry->m_sequence_data->getFPS();
|
||||
|
||||
for(int i = 0; seek_frame > 0; i++)
|
||||
{
|
||||
float pitch;
|
||||
pitch_property->read(frame_start + i, &pitch);
|
||||
const double factor = seek_frame > 1.0 ? 1.0 : seek_frame;
|
||||
target_frame += pitch * factor;
|
||||
seek_frame--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target_frame = seek_frame;
|
||||
}
|
||||
|
||||
double seekpos = target_frame / m_entry->m_sequence_data->getFPS();
|
||||
|
||||
m_handle->setPitch(1.0f);
|
||||
m_handle->seek(seekpos);
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ typedef uint32_t cuuint32_t;
|
|||
typedef uint64_t cuuint64_t;
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__)
|
||||
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__) || defined(__ppc64__) || defined(__PPC64__)
|
||||
typedef unsigned long long CUdeviceptr;
|
||||
#else
|
||||
typedef unsigned int CUdeviceptr;
|
||||
|
|
|
@ -84,7 +84,7 @@ typedef uint32_t hipuint32_t;
|
|||
typedef uint64_t hipuint64_t;
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__)
|
||||
#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__) || defined(__ppc64__) || defined(__PPC64__)
|
||||
typedef unsigned long long hipDeviceptr_t;
|
||||
#else
|
||||
typedef unsigned int hipDeviceptr_t;
|
||||
|
|
|
@ -281,6 +281,7 @@ endif()
|
|||
|
||||
if(WITH_CYCLES_EMBREE)
|
||||
add_definitions(-DWITH_EMBREE)
|
||||
add_definitions(-DEMBREE_MAJOR_VERSION=${EMBREE_MAJOR_VERSION})
|
||||
include_directories(
|
||||
SYSTEM
|
||||
${EMBREE_INCLUDE_DIRS}
|
||||
|
|
|
@ -51,6 +51,12 @@ if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
|
|||
endif()
|
||||
|
||||
if(WITH_USD)
|
||||
# Silence warning from USD headers using deprecated TBB header.
|
||||
add_definitions(
|
||||
-D__TBB_show_deprecation_message_atomic_H
|
||||
-D__TBB_show_deprecation_message_task_H
|
||||
)
|
||||
|
||||
list(APPEND INC_SYS
|
||||
${USD_INCLUDE_DIRS}
|
||||
)
|
||||
|
|
|
@ -403,7 +403,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
|||
|
||||
time_limit: FloatProperty(
|
||||
name="Time Limit",
|
||||
description="Limit the render time (excluding synchronization time)."
|
||||
description="Limit the render time (excluding synchronization time). "
|
||||
"Zero disables the limit",
|
||||
min=0.0,
|
||||
default=0.0,
|
||||
|
|
|
@ -609,59 +609,60 @@ void BlenderSync::sync_particle_hair(
|
|||
}
|
||||
}
|
||||
|
||||
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves b_curves)
|
||||
static const float *find_radius_attribute(BL::Curves b_curves)
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_curves.attributes) {
|
||||
if (b_attribute.name() != "radius") {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
|
||||
continue;
|
||||
}
|
||||
return BL::FloatAttribute{b_attribute};
|
||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
||||
if (b_float_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
}
|
||||
return std::nullopt;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static BL::FloatVectorAttribute find_curves_position_attribute(BL::Curves b_curves)
|
||||
static const float (*find_position_attribute(BL::Curves b_curves))[3]
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_curves.attributes) {
|
||||
if (b_attribute.name() != "position") {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
|
||||
continue;
|
||||
}
|
||||
return BL::FloatVectorAttribute{b_attribute};
|
||||
BL::FloatVectorAttribute b_float3_attribute{b_attribute};
|
||||
if (b_float3_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
|
||||
}
|
||||
/* The position attribute must exist. */
|
||||
assert(false);
|
||||
return BL::FloatVectorAttribute{b_curves.attributes[0]};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename TypeInCycles, typename GetValueAtIndex>
|
||||
static void fill_generic_attribute(BL::Curves &b_curves,
|
||||
static void fill_generic_attribute(const int num_curves,
|
||||
const int num_points,
|
||||
TypeInCycles *data,
|
||||
const AttributeElement element,
|
||||
const GetValueAtIndex &get_value_at_index)
|
||||
{
|
||||
switch (element) {
|
||||
case ATTR_ELEMENT_CURVE_KEY: {
|
||||
const int num_points = b_curves.points.length();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = get_value_at_index(i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ATTR_ELEMENT_CURVE: {
|
||||
const int num_verts = b_curves.curves.length();
|
||||
for (int i = 0; i < num_verts; i++) {
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
data[i] = get_value_at_index(i);
|
||||
}
|
||||
break;
|
||||
|
@ -681,6 +682,7 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo
|
|||
}
|
||||
|
||||
BL::FloatVectorAttribute b_vector_attribute(b_attribute);
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
const int num_curve_keys = hair->get_curve_keys().size();
|
||||
|
||||
/* Find or add attribute */
|
||||
|
@ -698,23 +700,24 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo
|
|||
float3 *mP = attr_mP->data_float3() + step * num_curve_keys;
|
||||
|
||||
for (int i = 0; i < num_curve_keys; i++) {
|
||||
mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
|
||||
mP[i] = P[i] + make_float3(src[i][0], src[i][1], src[i][2]) * relative_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void attr_create_uv(AttributeSet &attributes,
|
||||
BL::Curves &b_curves,
|
||||
const int num_curves,
|
||||
const int num_points,
|
||||
BL::Attribute &b_attribute,
|
||||
const ustring name)
|
||||
{
|
||||
BL::Float2Attribute b_float2_attribute{b_attribute};
|
||||
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(ATTR_STD_UV, name);
|
||||
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(b_curves, data, ATTR_ELEMENT_CURVE, [&](int i) {
|
||||
BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
|
||||
return make_float2(v[0], v[1]);
|
||||
fill_generic_attribute(num_curves, num_points, data, ATTR_ELEMENT_CURVE, [&](int i) {
|
||||
return make_float2(src[i][0], src[i][1]);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -724,6 +727,9 @@ static void attr_create_generic(Scene *scene,
|
|||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_keys = b_curves.points.length();
|
||||
const int num_curves = b_curves.curves.length();
|
||||
|
||||
AttributeSet &attributes = hair->attributes;
|
||||
static const ustring u_velocity("velocity");
|
||||
const bool need_uv = hair->need_attribute(scene, ATTR_STD_UV);
|
||||
|
@ -743,7 +749,7 @@ static void attr_create_generic(Scene *scene,
|
|||
/* Weak, use first float2 attribute as standard UV. */
|
||||
if (need_uv && !have_uv && b_data_type == BL::Attribute::data_type_FLOAT2 &&
|
||||
b_domain == BL::Attribute::domain_CURVE) {
|
||||
attr_create_uv(attributes, b_curves, b_attribute, name);
|
||||
attr_create_uv(attributes, num_curves, num_keys, b_attribute, name);
|
||||
have_uv = true;
|
||||
continue;
|
||||
}
|
||||
|
@ -773,57 +779,70 @@ static void attr_create_generic(Scene *scene,
|
|||
switch (b_data_type) {
|
||||
case BL::Attribute::data_type_FLOAT: {
|
||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
||||
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(
|
||||
b_curves, data, element, [&](int i) { return b_float_attribute.data[i].value(); });
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) { return src[i]; });
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_BOOLEAN: {
|
||||
BL::BoolAttribute b_bool_attribute{b_attribute};
|
||||
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(b_curves, data, element, [&](int i) {
|
||||
return (float)b_bool_attribute.data[i].value();
|
||||
});
|
||||
fill_generic_attribute(
|
||||
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT: {
|
||||
BL::IntAttribute b_int_attribute{b_attribute};
|
||||
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(b_curves, data, element, [&](int i) {
|
||||
return (float)b_int_attribute.data[i].value();
|
||||
});
|
||||
fill_generic_attribute(
|
||||
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeVector, element);
|
||||
float3 *data = attr->data_float3();
|
||||
fill_generic_attribute(b_curves, data, element, [&](int i) {
|
||||
BL::Array<float, 3> v = b_vector_attribute.data[i].vector();
|
||||
return make_float3(v[0], v[1], v[2]);
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float3(src[i][0], src[i][1], src[i][2]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_BYTE_COLOR: {
|
||||
BL::ByteColorAttribute b_color_attribute{b_attribute};
|
||||
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][1])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][2])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][3])));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_COLOR: {
|
||||
BL::FloatColorAttribute b_color_attribute{b_attribute};
|
||||
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
fill_generic_attribute(b_curves, data, element, [&](int i) {
|
||||
BL::Array<float, 4> v = b_color_attribute.data[i].color();
|
||||
return make_float4(v[0], v[1], v[2], v[3]);
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT2: {
|
||||
BL::Float2Attribute b_float2_attribute{b_attribute};
|
||||
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(b_curves, data, element, [&](int i) {
|
||||
BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
|
||||
return make_float2(v[0], v[1]);
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float2(src[i][0], src[i][1]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -834,27 +853,28 @@ static void attr_create_generic(Scene *scene,
|
|||
}
|
||||
}
|
||||
|
||||
static float4 hair_point_as_float4(BL::FloatVectorAttribute b_attr_position,
|
||||
std::optional<BL::FloatAttribute> b_attr_radius,
|
||||
const int index)
|
||||
static float4 curve_point_as_float4(const float (*b_attr_position)[3],
|
||||
const float *b_attr_radius,
|
||||
const int index)
|
||||
{
|
||||
float4 mP = float3_to_float4(get_float3(b_attr_position.data[index].vector()));
|
||||
mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.005f;
|
||||
float4 mP = make_float4(
|
||||
b_attr_position[index][0], b_attr_position[index][1], b_attr_position[index][2], 0.0f);
|
||||
mP.w = b_attr_radius ? b_attr_radius[index] : 0.005f;
|
||||
return mP;
|
||||
}
|
||||
|
||||
static float4 interpolate_hair_points(BL::FloatVectorAttribute b_attr_position,
|
||||
std::optional<BL::FloatAttribute> b_attr_radius,
|
||||
const int first_point_index,
|
||||
const int num_points,
|
||||
const float step)
|
||||
static float4 interpolate_curve_points(const float (*b_attr_position)[3],
|
||||
const float *b_attr_radius,
|
||||
const int first_point_index,
|
||||
const int num_points,
|
||||
const float step)
|
||||
{
|
||||
const float curve_t = step * (num_points - 1);
|
||||
const int point_a = clamp((int)curve_t, 0, num_points - 1);
|
||||
const int point_b = min(point_a + 1, num_points - 1);
|
||||
const float t = curve_t - (float)point_a;
|
||||
return lerp(hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
|
||||
hair_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
|
||||
return lerp(curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
|
||||
curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
|
||||
t);
|
||||
}
|
||||
|
||||
|
@ -864,8 +884,6 @@ static void export_hair_curves(Scene *scene,
|
|||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
/* TODO: optimize so we can straight memcpy arrays from Blender? */
|
||||
|
||||
const int num_keys = b_curves.points.length();
|
||||
const int num_curves = b_curves.curves.length();
|
||||
|
||||
|
@ -879,7 +897,6 @@ static void export_hair_curves(Scene *scene,
|
|||
/* Add requested attributes. */
|
||||
float *attr_intercept = NULL;
|
||||
float *attr_length = NULL;
|
||||
float *attr_random = NULL;
|
||||
|
||||
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
|
||||
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT)->data_float();
|
||||
|
@ -888,28 +905,40 @@ static void export_hair_curves(Scene *scene,
|
|||
attr_length = hair->attributes.add(ATTR_STD_CURVE_LENGTH)->data_float();
|
||||
}
|
||||
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) {
|
||||
attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float();
|
||||
float *attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float();
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
attr_random[i] = hash_uint2_to_float(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves);
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
|
||||
const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_curves);
|
||||
const float *b_attr_radius = find_radius_attribute(b_curves);
|
||||
|
||||
std::copy(point_offsets, point_offsets + num_curves, curve_first_key);
|
||||
std::fill(curve_shader, curve_shader + num_curves, 0);
|
||||
if (b_attr_radius) {
|
||||
std::copy(b_attr_radius, b_attr_radius + num_keys, curve_radius);
|
||||
}
|
||||
else {
|
||||
std::fill(curve_radius, curve_radius + num_curves, 0.005f);
|
||||
}
|
||||
|
||||
/* Export curves and points. */
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
const int first_point_index = b_curves.curve_offset_data[i].value();
|
||||
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
|
||||
const int first_point_index = point_offsets[i];
|
||||
const int num_points = point_offsets[i + 1] - first_point_index;
|
||||
|
||||
float3 prev_co = zero_float3();
|
||||
float length = 0.0f;
|
||||
|
||||
/* Position and radius. */
|
||||
for (int j = 0; j < num_points; j++) {
|
||||
const int point_offset = first_point_index + j;
|
||||
const float3 co = get_float3(b_attr_position.data[point_offset].vector());
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[point_offset].value() : 0.005f;
|
||||
const int point = first_point_index + j;
|
||||
const float3 co = make_float3(
|
||||
b_attr_position[point][0], b_attr_position[point][1], b_attr_position[point][2]);
|
||||
|
||||
curve_keys[point_offset] = co;
|
||||
curve_radius[point_offset] = radius;
|
||||
curve_keys[point] = co;
|
||||
|
||||
if (attr_length || attr_intercept) {
|
||||
if (j > 0) {
|
||||
|
@ -918,7 +947,7 @@ static void export_hair_curves(Scene *scene,
|
|||
prev_co = co;
|
||||
|
||||
if (attr_intercept) {
|
||||
attr_intercept[point_offset] = length;
|
||||
attr_intercept[point] = length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -926,8 +955,8 @@ static void export_hair_curves(Scene *scene,
|
|||
/* Normalized 0..1 attribute along curve. */
|
||||
if (attr_intercept && length > 0.0f) {
|
||||
for (int j = 1; j < num_points; j++) {
|
||||
const int point_offset = first_point_index + j;
|
||||
attr_intercept[point_offset] /= length;
|
||||
const int point = first_point_index + j;
|
||||
attr_intercept[point] /= length;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -935,15 +964,6 @@ static void export_hair_curves(Scene *scene,
|
|||
if (attr_length) {
|
||||
attr_length[i] = length;
|
||||
}
|
||||
|
||||
/* Random number per curve. */
|
||||
if (attr_random != NULL) {
|
||||
attr_random[i] = hash_uint2_to_float(i, 0);
|
||||
}
|
||||
|
||||
/* Curve. */
|
||||
curve_shader[i] = 0;
|
||||
curve_first_key[i] = first_point_index;
|
||||
}
|
||||
|
||||
attr_create_generic(scene, hair, b_curves, need_motion, motion_scale);
|
||||
|
@ -968,12 +988,13 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
|
|||
int num_motion_keys = 0;
|
||||
int curve_index = 0;
|
||||
|
||||
BL::FloatVectorAttribute b_attr_position = find_curves_position_attribute(b_curves);
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
|
||||
const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_curves);
|
||||
const float *b_attr_radius = find_radius_attribute(b_curves);
|
||||
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
const int first_point_index = b_curves.curve_offset_data[i].value();
|
||||
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
|
||||
const int first_point_index = point_offsets[i];
|
||||
const int num_points = point_offsets[i + 1] - first_point_index;
|
||||
|
||||
Hair::Curve curve = hair->get_curve(curve_index);
|
||||
curve_index++;
|
||||
|
@ -981,10 +1002,10 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
|
|||
if (num_points == curve.num_keys) {
|
||||
/* Number of keys matches. */
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
int point_index = first_point_index + i;
|
||||
int point = first_point_index + i;
|
||||
|
||||
if (point_index < num_keys) {
|
||||
mP[num_motion_keys] = hair_point_as_float4(b_attr_position, b_attr_radius, point_index);
|
||||
if (point < num_keys) {
|
||||
mP[num_motion_keys] = curve_point_as_float4(b_attr_position, b_attr_radius, point);
|
||||
num_motion_keys++;
|
||||
|
||||
if (!have_motion) {
|
||||
|
@ -1003,7 +1024,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
|
|||
const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f;
|
||||
for (int i = 0; i < curve.num_keys; i++) {
|
||||
const float step = i * step_size;
|
||||
mP[num_motion_keys] = interpolate_hair_points(
|
||||
mP[num_motion_keys] = interpolate_curve_points(
|
||||
b_attr_position, b_attr_radius, first_point_index, num_points, step);
|
||||
num_motion_keys++;
|
||||
}
|
||||
|
|
|
@ -10,22 +10,12 @@
|
|||
#include "blender/sync.h"
|
||||
#include "blender/util.h"
|
||||
|
||||
#include "util/color.h"
|
||||
#include "util/foreach.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
template<typename TypeInCycles, typename GetValueAtIndex>
|
||||
static void fill_generic_attribute(BL::PointCloud &b_pointcloud,
|
||||
TypeInCycles *data,
|
||||
const GetValueAtIndex &get_value_at_index)
|
||||
{
|
||||
const int num_points = b_pointcloud.points.length();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = get_value_at_index(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void attr_create_motion(PointCloud *pointcloud,
|
||||
BL::Attribute &b_attribute,
|
||||
const float motion_scale)
|
||||
|
@ -63,6 +53,11 @@ static void copy_attributes(PointCloud *pointcloud,
|
|||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_points = b_pointcloud.points.length();
|
||||
if (num_points == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
AttributeSet &attributes = pointcloud->attributes;
|
||||
static const ustring u_velocity("velocity");
|
||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
||||
|
@ -81,56 +76,73 @@ static void copy_attributes(PointCloud *pointcloud,
|
|||
switch (b_data_type) {
|
||||
case BL::Attribute::data_type_FLOAT: {
|
||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
||||
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(
|
||||
b_pointcloud, data, [&](int i) { return b_float_attribute.data[i].value(); });
|
||||
std::copy(src, src + num_points, data);
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_BOOLEAN: {
|
||||
BL::BoolAttribute b_bool_attribute{b_attribute};
|
||||
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(
|
||||
b_pointcloud, data, [&](int i) { return (float)b_bool_attribute.data[i].value(); });
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = float(src[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT: {
|
||||
BL::IntAttribute b_int_attribute{b_attribute};
|
||||
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(
|
||||
b_pointcloud, data, [&](int i) { return (float)b_int_attribute.data[i].value(); });
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = float(src[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeVector, element);
|
||||
float3 *data = attr->data_float3();
|
||||
fill_generic_attribute(b_pointcloud, data, [&](int i) {
|
||||
BL::Array<float, 3> v = b_vector_attribute.data[i].vector();
|
||||
return make_float3(v[0], v[1], v[2]);
|
||||
});
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float3(src[i][0], src[i][1], src[i][2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_BYTE_COLOR: {
|
||||
BL::ByteColorAttribute b_color_attribute{b_attribute};
|
||||
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][1])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][2])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][3])));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_COLOR: {
|
||||
BL::FloatColorAttribute b_color_attribute{b_attribute};
|
||||
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
fill_generic_attribute(b_pointcloud, data, [&](int i) {
|
||||
BL::Array<float, 4> v = b_color_attribute.data[i].color();
|
||||
return make_float4(v[0], v[1], v[2], v[3]);
|
||||
});
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT2: {
|
||||
BL::Float2Attribute b_float2_attribute{b_attribute};
|
||||
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(b_pointcloud, data, [&](int i) {
|
||||
BL::Array<float, 2> v = b_float2_attribute.data[i].vector();
|
||||
return make_float2(v[0], v[1]);
|
||||
});
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float2(src[i][0], src[i][1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -140,7 +152,7 @@ static void copy_attributes(PointCloud *pointcloud,
|
|||
}
|
||||
}
|
||||
|
||||
static std::optional<BL::FloatAttribute> find_radius_attribute(BL::PointCloud b_pointcloud)
|
||||
static const float *find_radius_attribute(BL::PointCloud b_pointcloud)
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
||||
if (b_attribute.name() != "radius") {
|
||||
|
@ -149,12 +161,16 @@ static std::optional<BL::FloatAttribute> find_radius_attribute(BL::PointCloud b_
|
|||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
|
||||
continue;
|
||||
}
|
||||
return BL::FloatAttribute{b_attribute};
|
||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
||||
if (b_float_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
}
|
||||
return std::nullopt;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static BL::FloatVectorAttribute find_position_attribute(BL::PointCloud b_pointcloud)
|
||||
static const float (*find_position_attribute(BL::PointCloud b_pointcloud))[3]
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
||||
if (b_attribute.name() != "position") {
|
||||
|
@ -163,11 +179,15 @@ static BL::FloatVectorAttribute find_position_attribute(BL::PointCloud b_pointcl
|
|||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
|
||||
continue;
|
||||
}
|
||||
return BL::FloatVectorAttribute{b_attribute};
|
||||
BL::FloatVectorAttribute b_float3_attribute{b_attribute};
|
||||
if (b_float3_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
|
||||
}
|
||||
/* The position attribute must exist. */
|
||||
assert(false);
|
||||
return BL::FloatVectorAttribute{b_pointcloud.attributes[0]};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void export_pointcloud(Scene *scene,
|
||||
|
@ -176,34 +196,36 @@ static void export_pointcloud(Scene *scene,
|
|||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
/* TODO: optimize so we can straight memcpy arrays from Blender? */
|
||||
const int num_points = b_pointcloud.points.length();
|
||||
pointcloud->resize(num_points);
|
||||
|
||||
/* Add requested attributes. */
|
||||
Attribute *attr_random = NULL;
|
||||
if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
|
||||
attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
|
||||
float3 *points = pointcloud->get_points().data();
|
||||
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
points[i] = make_float3(b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
|
||||
}
|
||||
|
||||
/* Reserve memory. */
|
||||
const int num_points = b_pointcloud.points.length();
|
||||
pointcloud->reserve(num_points);
|
||||
const float *b_attr_radius = find_radius_attribute(b_pointcloud);
|
||||
float *radius = pointcloud->get_radius().data();
|
||||
if (b_attr_radius) {
|
||||
std::copy(b_attr_radius, b_attr_radius + num_points, radius);
|
||||
}
|
||||
else {
|
||||
std::fill(radius, radius + num_points, 0.01f);
|
||||
}
|
||||
|
||||
BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud);
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud);
|
||||
int *shader = pointcloud->get_shader().data();
|
||||
std::fill(shader, shader + num_points, 0);
|
||||
|
||||
/* Export points. */
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
const float3 co = get_float3(b_attr_position.data[i].vector());
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f;
|
||||
pointcloud->add_point(co, radius);
|
||||
|
||||
/* Random number per point. */
|
||||
if (attr_random != NULL) {
|
||||
attr_random->add(hash_uint2_to_float(i, 0));
|
||||
if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
|
||||
Attribute *attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
|
||||
float *data = attr_random->data_float();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = hash_uint2_to_float(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Export attributes */
|
||||
copy_attributes(pointcloud, b_pointcloud, need_motion, motion_scale);
|
||||
}
|
||||
|
||||
|
@ -220,22 +242,22 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
|
|||
new_attribute = true;
|
||||
}
|
||||
|
||||
/* Export motion points. */
|
||||
const int num_points = pointcloud->num_points();
|
||||
// Point cloud attributes are stored as float4 with the radius
|
||||
// in the w element. This is explict now as float3 is no longer
|
||||
// interchangeable with float4 as it is packed now.
|
||||
/* Point cloud attributes are stored as float4 with the radius in the w element.
|
||||
* This is explict now as float3 is no longer interchangeable with float4 as it
|
||||
* is packed now. */
|
||||
float4 *mP = attr_mP->data_float4() + motion_step * num_points;
|
||||
bool have_motion = false;
|
||||
const array<float3> &pointcloud_points = pointcloud->get_points();
|
||||
|
||||
const int b_points_num = b_pointcloud.points.length();
|
||||
BL::FloatVectorAttribute b_attr_position = find_position_attribute(b_pointcloud);
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_radius_attribute(b_pointcloud);
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
|
||||
const float *b_attr_radius = find_radius_attribute(b_pointcloud);
|
||||
|
||||
for (int i = 0; i < std::min(num_points, b_points_num); i++) {
|
||||
const float3 P = get_float3(b_attr_position.data[i].vector());
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[i].value() : 0.01f;
|
||||
const float3 P = make_float3(
|
||||
b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
|
||||
const float radius = b_attr_radius ? b_attr_radius[i] : 0.01f;
|
||||
mP[i] = make_float4(P.x, P.y, P.z, radius);
|
||||
have_motion = have_motion || (P != pointcloud_points[i]);
|
||||
}
|
||||
|
@ -277,7 +299,7 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
|
|||
0.0f;
|
||||
export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale);
|
||||
|
||||
/* update original sockets */
|
||||
/* Update original sockets. */
|
||||
for (const SocketType &socket : new_pointcloud.type->inputs) {
|
||||
/* Those sockets are updated in sync_object, so do not modify them. */
|
||||
if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
|
||||
|
@ -292,7 +314,7 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
|
|||
pointcloud->attributes.attributes.push_back(std::move(attr));
|
||||
}
|
||||
|
||||
/* tag update */
|
||||
/* Tag update. */
|
||||
const bool rebuild = (pointcloud && old_numpoints != pointcloud->num_points());
|
||||
pointcloud->tag_update(scene, rebuild);
|
||||
}
|
||||
|
|
|
@ -61,6 +61,11 @@ if(WITH_CYCLES_EMBREE)
|
|||
list(APPEND LIB
|
||||
${EMBREE_LIBRARIES}
|
||||
)
|
||||
if(EMBREE_SYCL_SUPPORT)
|
||||
list(APPEND LIB
|
||||
${SYCL_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
cycles_add_library(cycles_bvh "${LIB}" ${SRC} ${SRC_HEADERS})
|
||||
|
|
|
@ -17,7 +17,11 @@
|
|||
|
||||
#ifdef WITH_EMBREE
|
||||
|
||||
# include <embree3/rtcore_geometry.h>
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
# include <embree4/rtcore_geometry.h>
|
||||
# else
|
||||
# include <embree3/rtcore_geometry.h>
|
||||
# endif
|
||||
|
||||
# include "bvh/embree.h"
|
||||
|
||||
|
@ -128,7 +132,11 @@ void BVHEmbree::build(Progress &progress, Stats *stats, RTCDevice rtc_device_)
|
|||
scene = rtcNewScene(rtc_device);
|
||||
const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
|
||||
(compact ? RTC_SCENE_FLAG_COMPACT : RTC_SCENE_FLAG_NONE) |
|
||||
RTC_SCENE_FLAG_ROBUST;
|
||||
RTC_SCENE_FLAG_ROBUST
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
| RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS
|
||||
# endif
|
||||
;
|
||||
rtcSetSceneFlags(scene, scene_flags);
|
||||
build_quality = dynamic ? RTC_BUILD_QUALITY_LOW :
|
||||
(params.use_spatial_split ? RTC_BUILD_QUALITY_HIGH :
|
||||
|
@ -226,6 +234,9 @@ void BVHEmbree::add_instance(Object *ob, int i)
|
|||
|
||||
rtcSetGeometryUserData(geom_id, (void *)instance_bvh->scene);
|
||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
|
||||
# endif
|
||||
|
||||
rtcCommitGeometry(geom_id);
|
||||
rtcAttachGeometryByID(scene, geom_id, i * 2);
|
||||
|
@ -267,9 +278,13 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
|
|||
set_tri_vertex_buffer(geom_id, mesh, false);
|
||||
|
||||
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
|
||||
# else
|
||||
rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func);
|
||||
rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_intersection_func);
|
||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||
# endif
|
||||
|
||||
rtcCommitGeometry(geom_id);
|
||||
rtcAttachGeometryByID(scene, geom_id, i * 2);
|
||||
|
@ -494,9 +509,13 @@ void BVHEmbree::add_points(const Object *ob, const PointCloud *pointcloud, int i
|
|||
set_point_vertex_buffer(geom_id, pointcloud, false);
|
||||
|
||||
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
|
||||
# else
|
||||
rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_func_backface_cull);
|
||||
rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func_backface_cull);
|
||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||
# endif
|
||||
|
||||
rtcCommitGeometry(geom_id);
|
||||
rtcAttachGeometryByID(scene, geom_id, i * 2);
|
||||
|
@ -553,6 +572,10 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
|||
set_curve_vertex_buffer(geom_id, hair, false);
|
||||
|
||||
rtcSetGeometryUserData(geom_id, (void *)prim_offset);
|
||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
rtcSetGeometryEnableFilterFunctionFromArguments(geom_id, true);
|
||||
# else
|
||||
if (hair->curve_shape == CURVE_RIBBON) {
|
||||
rtcSetGeometryIntersectFilterFunction(geom_id, kernel_embree_filter_intersection_func);
|
||||
rtcSetGeometryOccludedFilterFunction(geom_id, kernel_embree_filter_occluded_func);
|
||||
|
@ -562,7 +585,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
|
|||
rtcSetGeometryOccludedFilterFunction(geom_id,
|
||||
kernel_embree_filter_occluded_func_backface_cull);
|
||||
}
|
||||
rtcSetGeometryMask(geom_id, ob->visibility_for_tracing());
|
||||
# endif
|
||||
|
||||
rtcCommitGeometry(geom_id);
|
||||
rtcAttachGeometryByID(scene, geom_id, i * 2 + 1);
|
||||
|
|
|
@ -6,8 +6,13 @@
|
|||
|
||||
#ifdef WITH_EMBREE
|
||||
|
||||
# include <embree3/rtcore.h>
|
||||
# include <embree3/rtcore_scene.h>
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
# include <embree4/rtcore.h>
|
||||
# include <embree4/rtcore_scene.h>
|
||||
# else
|
||||
# include <embree3/rtcore.h>
|
||||
# include <embree3/rtcore_scene.h>
|
||||
# endif
|
||||
|
||||
# include "bvh/bvh.h"
|
||||
# include "bvh/params.h"
|
||||
|
|
|
@ -176,12 +176,10 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
|
|||
else()
|
||||
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/../kernel/libcycles_kernel_oneapi${cycles_kernel_oneapi_lib_suffix}.so)
|
||||
endif()
|
||||
list(APPEND LIB ${cycles_kernel_oneapi_lib})
|
||||
if(WIN32)
|
||||
list(APPEND LIB debug ${SYCL_LIBRARY_DEBUG} optimized ${SYCL_LIBRARY})
|
||||
else()
|
||||
list(APPEND LIB ${SYCL_LIBRARY})
|
||||
endif()
|
||||
list(APPEND LIB
|
||||
${cycles_kernel_oneapi_lib}
|
||||
${SYCL_LIBRARIES}
|
||||
)
|
||||
list(APPEND SRC
|
||||
${SRC_ONEAPI}
|
||||
)
|
||||
|
|
|
@ -14,7 +14,11 @@
|
|||
#endif
|
||||
|
||||
#ifdef WITH_EMBREE
|
||||
# include <embree3/rtcore.h>
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
# include <embree4/rtcore.h>
|
||||
# else
|
||||
# include <embree3/rtcore.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "device/cpu/kernel.h"
|
||||
|
|
|
@ -11,7 +11,11 @@
|
|||
#endif
|
||||
|
||||
#ifdef WITH_EMBREE
|
||||
# include <embree3/rtcore.h>
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
# include <embree4/rtcore.h>
|
||||
# else
|
||||
# include <embree3/rtcore.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "device/cpu/kernel.h"
|
||||
|
|
|
@ -445,12 +445,10 @@ void MetalKernelPipeline::compile()
|
|||
const std::string function_name = std::string("cycles_metal_") +
|
||||
device_kernel_as_string(device_kernel);
|
||||
|
||||
NSString *entryPoint = [@(function_name.c_str()) copy];
|
||||
|
||||
NSError *error = NULL;
|
||||
if (@available(macOS 11.0, *)) {
|
||||
MTLFunctionDescriptor *func_desc = [MTLIntersectionFunctionDescriptor functionDescriptor];
|
||||
func_desc.name = entryPoint;
|
||||
func_desc.name = [@(function_name.c_str()) copy];
|
||||
|
||||
if (pso_type != PSO_GENERIC) {
|
||||
func_desc.constantValues = GetConstantValues(&kernel_data_);
|
||||
|
@ -462,8 +460,6 @@ void MetalKernelPipeline::compile()
|
|||
function = [mtlLibrary newFunctionWithDescriptor:func_desc error:&error];
|
||||
}
|
||||
|
||||
[entryPoint release];
|
||||
|
||||
if (function == nil) {
|
||||
NSString *err = [error localizedDescription];
|
||||
string errors = [err UTF8String];
|
||||
|
@ -471,7 +467,7 @@ void MetalKernelPipeline::compile()
|
|||
return;
|
||||
}
|
||||
|
||||
function.label = [entryPoint copy];
|
||||
function.label = [@(function_name.c_str()) copy];
|
||||
|
||||
if (use_metalrt) {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
|
|
|
@ -80,6 +80,12 @@ if(EXISTS ${USD_INCLUDE_DIR}/pxr/imaging/hgiGL)
|
|||
list(APPEND SRC_HD_CYCLES_HEADERS display_driver.h)
|
||||
endif()
|
||||
|
||||
# Silence warning from USD headers using deprecated TBB header.
|
||||
add_definitions(
|
||||
-D__TBB_show_deprecation_message_atomic_H
|
||||
-D__TBB_show_deprecation_message_task_H
|
||||
)
|
||||
|
||||
include_directories(${INC})
|
||||
include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
// Include first to avoid "NOGDI" definition set in Cycles headers
|
||||
# ifndef NOMINMAX
|
||||
# define NOMINMAX
|
||||
# endif
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <Windows.h>
|
||||
#endif
|
||||
|
||||
|
|
|
@ -370,6 +370,16 @@ VtValue convertFromCyclesArray(const array<SrcType> &value)
|
|||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCyclesArray<float2, GfVec2f>(const array<float2> &value)
|
||||
{
|
||||
VtVec2fArray convertedValue;
|
||||
convertedValue.reserve(value.size());
|
||||
for (const auto &element : value) {
|
||||
convertedValue.push_back(GfVec2f(element.x, element.y));
|
||||
}
|
||||
return VtValue(convertedValue);
|
||||
}
|
||||
|
||||
template<> VtValue convertFromCyclesArray<float3, GfVec3f>(const array<float3> &value)
|
||||
{
|
||||
VtVec3fArray convertedValue;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "device/device.h"
|
||||
#include "device/memory.h"
|
||||
#include "device/queue.h"
|
||||
#include "integrator/pass_accessor_gpu.h"
|
||||
#include "session/buffers.h"
|
||||
#include "util/log.h"
|
||||
#include "util/progress.h"
|
||||
|
@ -105,4 +106,220 @@ Device *DenoiserGPU::ensure_denoiser_device(Progress *progress)
|
|||
return denoiser_device;
|
||||
}
|
||||
|
||||
DenoiserGPU::DenoiseContext::DenoiseContext(Device *device, const DenoiseTask &task)
|
||||
: denoise_params(task.params),
|
||||
render_buffers(task.render_buffers),
|
||||
buffer_params(task.buffer_params),
|
||||
guiding_buffer(device, "denoiser guiding passes buffer", true),
|
||||
num_samples(task.num_samples)
|
||||
{
|
||||
num_input_passes = 1;
|
||||
if (denoise_params.use_pass_albedo) {
|
||||
num_input_passes += 1;
|
||||
use_pass_albedo = true;
|
||||
pass_denoising_albedo = buffer_params.get_pass_offset(PASS_DENOISING_ALBEDO);
|
||||
if (denoise_params.use_pass_normal) {
|
||||
num_input_passes += 1;
|
||||
use_pass_normal = true;
|
||||
pass_denoising_normal = buffer_params.get_pass_offset(PASS_DENOISING_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (denoise_params.temporally_stable) {
|
||||
prev_output.device_pointer = render_buffers->buffer.device_pointer;
|
||||
|
||||
prev_output.offset = buffer_params.get_pass_offset(PASS_DENOISING_PREVIOUS);
|
||||
|
||||
prev_output.stride = buffer_params.stride;
|
||||
prev_output.pass_stride = buffer_params.pass_stride;
|
||||
|
||||
num_input_passes += 1;
|
||||
use_pass_motion = true;
|
||||
pass_motion = buffer_params.get_pass_offset(PASS_MOTION);
|
||||
}
|
||||
|
||||
use_guiding_passes = (num_input_passes - 1) > 0;
|
||||
|
||||
if (use_guiding_passes) {
|
||||
if (task.allow_inplace_modification) {
|
||||
guiding_params.device_pointer = render_buffers->buffer.device_pointer;
|
||||
|
||||
guiding_params.pass_albedo = pass_denoising_albedo;
|
||||
guiding_params.pass_normal = pass_denoising_normal;
|
||||
guiding_params.pass_flow = pass_motion;
|
||||
|
||||
guiding_params.stride = buffer_params.stride;
|
||||
guiding_params.pass_stride = buffer_params.pass_stride;
|
||||
}
|
||||
else {
|
||||
guiding_params.pass_stride = 0;
|
||||
if (use_pass_albedo) {
|
||||
guiding_params.pass_albedo = guiding_params.pass_stride;
|
||||
guiding_params.pass_stride += 3;
|
||||
}
|
||||
if (use_pass_normal) {
|
||||
guiding_params.pass_normal = guiding_params.pass_stride;
|
||||
guiding_params.pass_stride += 3;
|
||||
}
|
||||
if (use_pass_motion) {
|
||||
guiding_params.pass_flow = guiding_params.pass_stride;
|
||||
guiding_params.pass_stride += 2;
|
||||
}
|
||||
|
||||
guiding_params.stride = buffer_params.width;
|
||||
|
||||
guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height *
|
||||
guiding_params.pass_stride);
|
||||
guiding_params.device_pointer = guiding_buffer.device_pointer;
|
||||
}
|
||||
}
|
||||
|
||||
pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
|
||||
}
|
||||
|
||||
bool DenoiserGPU::denoise_filter_color_postprocess(const DenoiseContext &context,
|
||||
const DenoisePass &pass)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const int work_size = buffer_params.width * buffer_params.height;
|
||||
|
||||
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
|
||||
&buffer_params.full_x,
|
||||
&buffer_params.full_y,
|
||||
&buffer_params.width,
|
||||
&buffer_params.height,
|
||||
&buffer_params.offset,
|
||||
&buffer_params.stride,
|
||||
&buffer_params.pass_stride,
|
||||
&context.num_samples,
|
||||
&pass.noisy_offset,
|
||||
&pass.denoised_offset,
|
||||
&context.pass_sample_count,
|
||||
&pass.num_components,
|
||||
&pass.use_compositing);
|
||||
|
||||
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_POSTPROCESS, work_size, args);
|
||||
}
|
||||
|
||||
bool DenoiserGPU::denoise_filter_color_preprocess(const DenoiseContext &context,
|
||||
const DenoisePass &pass)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const int work_size = buffer_params.width * buffer_params.height;
|
||||
|
||||
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
|
||||
&buffer_params.full_x,
|
||||
&buffer_params.full_y,
|
||||
&buffer_params.width,
|
||||
&buffer_params.height,
|
||||
&buffer_params.offset,
|
||||
&buffer_params.stride,
|
||||
&buffer_params.pass_stride,
|
||||
&pass.denoised_offset);
|
||||
|
||||
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_PREPROCESS, work_size, args);
|
||||
}
|
||||
|
||||
bool DenoiserGPU::denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const int work_size = buffer_params.width * buffer_params.height;
|
||||
|
||||
DeviceKernelArguments args(&context.guiding_params.device_pointer,
|
||||
&context.guiding_params.pass_stride,
|
||||
&context.guiding_params.pass_albedo,
|
||||
&buffer_params.width,
|
||||
&buffer_params.height);
|
||||
|
||||
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_GUIDING_SET_FAKE_ALBEDO, work_size, args);
|
||||
}
|
||||
|
||||
void DenoiserGPU::denoise_color_read(const DenoiseContext &context, const DenoisePass &pass)
|
||||
{
|
||||
PassAccessor::PassAccessInfo pass_access_info;
|
||||
pass_access_info.type = pass.type;
|
||||
pass_access_info.mode = PassMode::NOISY;
|
||||
pass_access_info.offset = pass.noisy_offset;
|
||||
|
||||
/* Denoiser operates on passes which are used to calculate the approximation, and is never used
|
||||
* on the approximation. The latter is not even possible because OptiX does not support
|
||||
* denoising of semi-transparent pixels. */
|
||||
pass_access_info.use_approximate_shadow_catcher = false;
|
||||
pass_access_info.use_approximate_shadow_catcher_background = false;
|
||||
pass_access_info.show_active_pixels = false;
|
||||
|
||||
/* TODO(sergey): Consider adding support of actual exposure, to avoid clamping in extreme cases.
|
||||
*/
|
||||
const PassAccessorGPU pass_accessor(
|
||||
denoiser_queue_.get(), pass_access_info, 1.0f, context.num_samples);
|
||||
|
||||
PassAccessor::Destination destination(pass_access_info.type);
|
||||
destination.d_pixels = context.render_buffers->buffer.device_pointer +
|
||||
pass.denoised_offset * sizeof(float);
|
||||
destination.num_components = 3;
|
||||
destination.pixel_stride = context.buffer_params.pass_stride;
|
||||
|
||||
BufferParams buffer_params = context.buffer_params;
|
||||
buffer_params.window_x = 0;
|
||||
buffer_params.window_y = 0;
|
||||
buffer_params.window_width = buffer_params.width;
|
||||
buffer_params.window_height = buffer_params.height;
|
||||
|
||||
pass_accessor.get_render_tile_pixels(context.render_buffers, buffer_params, destination);
|
||||
}
|
||||
|
||||
void DenoiserGPU::denoise_pass(DenoiseContext &context, PassType pass_type)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const DenoisePass pass(pass_type, buffer_params);
|
||||
|
||||
if (pass.noisy_offset == PASS_UNUSED) {
|
||||
return;
|
||||
}
|
||||
if (pass.denoised_offset == PASS_UNUSED) {
|
||||
LOG(DFATAL) << "Missing denoised pass " << pass_type_as_string(pass_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass.use_denoising_albedo) {
|
||||
if (context.albedo_replaced_with_fake) {
|
||||
LOG(ERROR) << "Pass which requires albedo is denoised after fake albedo has been set.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (context.use_guiding_passes && !context.albedo_replaced_with_fake) {
|
||||
context.albedo_replaced_with_fake = true;
|
||||
if (!denoise_filter_guiding_set_fake_albedo(context)) {
|
||||
LOG(ERROR) << "Error replacing real albedo with the fake one.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read and preprocess noisy color input pass. */
|
||||
denoise_color_read(context, pass);
|
||||
if (!denoise_filter_color_preprocess(context, pass)) {
|
||||
LOG(ERROR) << "Error converting denoising passes to RGB buffer.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!denoise_run(context, pass)) {
|
||||
LOG(ERROR) << "Error running denoiser.";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store result in the combined pass of the render buffer.
|
||||
*
|
||||
* This will scale the denoiser result up to match the number of, possibly per-pixel, samples. */
|
||||
if (!denoise_filter_color_postprocess(context, pass)) {
|
||||
LOG(ERROR) << "Error copying denoiser result to the denoised pass.";
|
||||
return;
|
||||
}
|
||||
|
||||
denoiser_queue_->synchronize();
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -21,6 +21,9 @@ class DenoiserGPU : public Denoiser {
|
|||
bool allow_inplace_modification) override;
|
||||
|
||||
protected:
|
||||
class DenoisePass;
|
||||
class DenoiseContext;
|
||||
|
||||
/* All the parameters needed to perform buffer denoising on a device.
|
||||
* Is not really a task in its canonical terms (as in, is not an asynchronous running task). Is
|
||||
* more like a wrapper for all the arguments and parameters needed to perform denoising. Is a
|
||||
|
@ -41,12 +44,105 @@ class DenoiserGPU : public Denoiser {
|
|||
bool allow_inplace_modification;
|
||||
};
|
||||
|
||||
/* Read input color pass from the render buffer into the memory which corresponds to the noisy
|
||||
* input within the given context. Pixels are scaled to the number of samples, but are not
|
||||
* preprocessed yet. */
|
||||
void denoise_color_read(const DenoiseContext &context, const DenoisePass &pass);
|
||||
|
||||
/* Run corresponding filter kernels, preparing data for the denoiser or copying data from the
|
||||
* denoiser result to the render buffer. */
|
||||
bool denoise_filter_color_preprocess(const DenoiseContext &context, const DenoisePass &pass);
|
||||
bool denoise_filter_color_postprocess(const DenoiseContext &context, const DenoisePass &pass);
|
||||
bool denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context);
|
||||
|
||||
void denoise_pass(DenoiseContext &context, PassType pass_type);
|
||||
|
||||
/* Returns true if task is fully handled. */
|
||||
virtual bool denoise_buffer(const DenoiseTask & /*task*/) = 0;
|
||||
virtual bool denoise_run(const DenoiseContext &context, const DenoisePass &pass) = 0;
|
||||
|
||||
virtual Device *ensure_denoiser_device(Progress *progress) override;
|
||||
|
||||
unique_ptr<DeviceQueue> denoiser_queue_;
|
||||
|
||||
class DenoisePass {
|
||||
public:
|
||||
DenoisePass(const PassType type, const BufferParams &buffer_params) : type(type)
|
||||
{
|
||||
noisy_offset = buffer_params.get_pass_offset(type, PassMode::NOISY);
|
||||
denoised_offset = buffer_params.get_pass_offset(type, PassMode::DENOISED);
|
||||
|
||||
const PassInfo pass_info = Pass::get_info(type);
|
||||
num_components = pass_info.num_components;
|
||||
use_compositing = pass_info.use_compositing;
|
||||
use_denoising_albedo = pass_info.use_denoising_albedo;
|
||||
}
|
||||
|
||||
PassType type;
|
||||
|
||||
int noisy_offset;
|
||||
int denoised_offset;
|
||||
|
||||
int num_components;
|
||||
bool use_compositing;
|
||||
bool use_denoising_albedo;
|
||||
};
|
||||
|
||||
class DenoiseContext {
|
||||
public:
|
||||
explicit DenoiseContext(Device *device, const DenoiseTask &task);
|
||||
|
||||
const DenoiseParams &denoise_params;
|
||||
|
||||
RenderBuffers *render_buffers = nullptr;
|
||||
const BufferParams &buffer_params;
|
||||
|
||||
/* Previous output. */
|
||||
struct {
|
||||
device_ptr device_pointer = 0;
|
||||
|
||||
int offset = PASS_UNUSED;
|
||||
|
||||
int stride = -1;
|
||||
int pass_stride = -1;
|
||||
} prev_output;
|
||||
|
||||
/* Device-side storage of the guiding passes. */
|
||||
device_only_memory<float> guiding_buffer;
|
||||
|
||||
struct {
|
||||
device_ptr device_pointer = 0;
|
||||
|
||||
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
|
||||
int pass_albedo = PASS_UNUSED;
|
||||
int pass_normal = PASS_UNUSED;
|
||||
int pass_flow = PASS_UNUSED;
|
||||
|
||||
int stride = -1;
|
||||
int pass_stride = -1;
|
||||
} guiding_params;
|
||||
|
||||
/* Number of input passes. Including the color and extra auxiliary passes. */
|
||||
int num_input_passes = 0;
|
||||
bool use_guiding_passes = false;
|
||||
bool use_pass_albedo = false;
|
||||
bool use_pass_normal = false;
|
||||
bool use_pass_motion = false;
|
||||
|
||||
int num_samples = 0;
|
||||
|
||||
int pass_sample_count = PASS_UNUSED;
|
||||
|
||||
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
|
||||
int pass_denoising_albedo = PASS_UNUSED;
|
||||
int pass_denoising_normal = PASS_UNUSED;
|
||||
int pass_motion = PASS_UNUSED;
|
||||
|
||||
/* For passes which don't need albedo channel for denoising we replace the actual albedo with
|
||||
* the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with
|
||||
* the fake values and denoising of passes which do need albedo can no longer happen. */
|
||||
bool albedo_replaced_with_fake = false;
|
||||
};
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -218,154 +218,6 @@ uint OptiXDenoiser::get_device_type_mask() const
|
|||
return DEVICE_MASK_OPTIX;
|
||||
}
|
||||
|
||||
class OptiXDenoiser::DenoiseContext {
|
||||
public:
|
||||
explicit DenoiseContext(OptiXDevice *device, const DenoiseTask &task)
|
||||
: denoise_params(task.params),
|
||||
render_buffers(task.render_buffers),
|
||||
buffer_params(task.buffer_params),
|
||||
guiding_buffer(device, "denoiser guiding passes buffer", true),
|
||||
num_samples(task.num_samples)
|
||||
{
|
||||
num_input_passes = 1;
|
||||
if (denoise_params.use_pass_albedo) {
|
||||
num_input_passes += 1;
|
||||
use_pass_albedo = true;
|
||||
pass_denoising_albedo = buffer_params.get_pass_offset(PASS_DENOISING_ALBEDO);
|
||||
if (denoise_params.use_pass_normal) {
|
||||
num_input_passes += 1;
|
||||
use_pass_normal = true;
|
||||
pass_denoising_normal = buffer_params.get_pass_offset(PASS_DENOISING_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (denoise_params.temporally_stable) {
|
||||
prev_output.device_pointer = render_buffers->buffer.device_pointer;
|
||||
|
||||
prev_output.offset = buffer_params.get_pass_offset(PASS_DENOISING_PREVIOUS);
|
||||
|
||||
prev_output.stride = buffer_params.stride;
|
||||
prev_output.pass_stride = buffer_params.pass_stride;
|
||||
|
||||
num_input_passes += 1;
|
||||
use_pass_motion = true;
|
||||
pass_motion = buffer_params.get_pass_offset(PASS_MOTION);
|
||||
}
|
||||
|
||||
use_guiding_passes = (num_input_passes - 1) > 0;
|
||||
|
||||
if (use_guiding_passes) {
|
||||
if (task.allow_inplace_modification) {
|
||||
guiding_params.device_pointer = render_buffers->buffer.device_pointer;
|
||||
|
||||
guiding_params.pass_albedo = pass_denoising_albedo;
|
||||
guiding_params.pass_normal = pass_denoising_normal;
|
||||
guiding_params.pass_flow = pass_motion;
|
||||
|
||||
guiding_params.stride = buffer_params.stride;
|
||||
guiding_params.pass_stride = buffer_params.pass_stride;
|
||||
}
|
||||
else {
|
||||
guiding_params.pass_stride = 0;
|
||||
if (use_pass_albedo) {
|
||||
guiding_params.pass_albedo = guiding_params.pass_stride;
|
||||
guiding_params.pass_stride += 3;
|
||||
}
|
||||
if (use_pass_normal) {
|
||||
guiding_params.pass_normal = guiding_params.pass_stride;
|
||||
guiding_params.pass_stride += 3;
|
||||
}
|
||||
if (use_pass_motion) {
|
||||
guiding_params.pass_flow = guiding_params.pass_stride;
|
||||
guiding_params.pass_stride += 2;
|
||||
}
|
||||
|
||||
guiding_params.stride = buffer_params.width;
|
||||
|
||||
guiding_buffer.alloc_to_device(buffer_params.width * buffer_params.height *
|
||||
guiding_params.pass_stride);
|
||||
guiding_params.device_pointer = guiding_buffer.device_pointer;
|
||||
}
|
||||
}
|
||||
|
||||
pass_sample_count = buffer_params.get_pass_offset(PASS_SAMPLE_COUNT);
|
||||
}
|
||||
|
||||
const DenoiseParams &denoise_params;
|
||||
|
||||
RenderBuffers *render_buffers = nullptr;
|
||||
const BufferParams &buffer_params;
|
||||
|
||||
/* Previous output. */
|
||||
struct {
|
||||
device_ptr device_pointer = 0;
|
||||
|
||||
int offset = PASS_UNUSED;
|
||||
|
||||
int stride = -1;
|
||||
int pass_stride = -1;
|
||||
} prev_output;
|
||||
|
||||
/* Device-side storage of the guiding passes. */
|
||||
device_only_memory<float> guiding_buffer;
|
||||
|
||||
struct {
|
||||
device_ptr device_pointer = 0;
|
||||
|
||||
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
|
||||
int pass_albedo = PASS_UNUSED;
|
||||
int pass_normal = PASS_UNUSED;
|
||||
int pass_flow = PASS_UNUSED;
|
||||
|
||||
int stride = -1;
|
||||
int pass_stride = -1;
|
||||
} guiding_params;
|
||||
|
||||
/* Number of input passes. Including the color and extra auxiliary passes. */
|
||||
int num_input_passes = 0;
|
||||
bool use_guiding_passes = false;
|
||||
bool use_pass_albedo = false;
|
||||
bool use_pass_normal = false;
|
||||
bool use_pass_motion = false;
|
||||
|
||||
int num_samples = 0;
|
||||
|
||||
int pass_sample_count = PASS_UNUSED;
|
||||
|
||||
/* NOTE: Are only initialized when the corresponding guiding pass is enabled. */
|
||||
int pass_denoising_albedo = PASS_UNUSED;
|
||||
int pass_denoising_normal = PASS_UNUSED;
|
||||
int pass_motion = PASS_UNUSED;
|
||||
|
||||
/* For passes which don't need albedo channel for denoising we replace the actual albedo with
|
||||
* the (0.5, 0.5, 0.5). This flag indicates that the real albedo pass has been replaced with
|
||||
* the fake values and denoising of passes which do need albedo can no longer happen. */
|
||||
bool albedo_replaced_with_fake = false;
|
||||
};
|
||||
|
||||
class OptiXDenoiser::DenoisePass {
|
||||
public:
|
||||
DenoisePass(const PassType type, const BufferParams &buffer_params) : type(type)
|
||||
{
|
||||
noisy_offset = buffer_params.get_pass_offset(type, PassMode::NOISY);
|
||||
denoised_offset = buffer_params.get_pass_offset(type, PassMode::DENOISED);
|
||||
|
||||
const PassInfo pass_info = Pass::get_info(type);
|
||||
num_components = pass_info.num_components;
|
||||
use_compositing = pass_info.use_compositing;
|
||||
use_denoising_albedo = pass_info.use_denoising_albedo;
|
||||
}
|
||||
|
||||
PassType type;
|
||||
|
||||
int noisy_offset;
|
||||
int denoised_offset;
|
||||
|
||||
int num_components;
|
||||
bool use_compositing;
|
||||
bool use_denoising_albedo;
|
||||
};
|
||||
|
||||
bool OptiXDenoiser::denoise_buffer(const DenoiseTask &task)
|
||||
{
|
||||
OptiXDevice *const optix_device = static_cast<OptiXDevice *>(denoiser_device_);
|
||||
|
@ -421,151 +273,6 @@ bool OptiXDenoiser::denoise_filter_guiding_preprocess(const DenoiseContext &cont
|
|||
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_GUIDING_PREPROCESS, work_size, args);
|
||||
}
|
||||
|
||||
bool OptiXDenoiser::denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const int work_size = buffer_params.width * buffer_params.height;
|
||||
|
||||
DeviceKernelArguments args(&context.guiding_params.device_pointer,
|
||||
&context.guiding_params.pass_stride,
|
||||
&context.guiding_params.pass_albedo,
|
||||
&buffer_params.width,
|
||||
&buffer_params.height);
|
||||
|
||||
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_GUIDING_SET_FAKE_ALBEDO, work_size, args);
|
||||
}
|
||||
|
||||
void OptiXDenoiser::denoise_pass(DenoiseContext &context, PassType pass_type)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const DenoisePass pass(pass_type, buffer_params);
|
||||
|
||||
if (pass.noisy_offset == PASS_UNUSED) {
|
||||
return;
|
||||
}
|
||||
if (pass.denoised_offset == PASS_UNUSED) {
|
||||
LOG(DFATAL) << "Missing denoised pass " << pass_type_as_string(pass_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass.use_denoising_albedo) {
|
||||
if (context.albedo_replaced_with_fake) {
|
||||
LOG(ERROR) << "Pass which requires albedo is denoised after fake albedo has been set.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (context.use_guiding_passes && !context.albedo_replaced_with_fake) {
|
||||
context.albedo_replaced_with_fake = true;
|
||||
if (!denoise_filter_guiding_set_fake_albedo(context)) {
|
||||
LOG(ERROR) << "Error replacing real albedo with the fake one.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read and preprocess noisy color input pass. */
|
||||
denoise_color_read(context, pass);
|
||||
if (!denoise_filter_color_preprocess(context, pass)) {
|
||||
LOG(ERROR) << "Error converting denoising passes to RGB buffer.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!denoise_run(context, pass)) {
|
||||
LOG(ERROR) << "Error running OptiX denoiser.";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store result in the combined pass of the render buffer.
|
||||
*
|
||||
* This will scale the denoiser result up to match the number of, possibly per-pixel, samples. */
|
||||
if (!denoise_filter_color_postprocess(context, pass)) {
|
||||
LOG(ERROR) << "Error copying denoiser result to the denoised pass.";
|
||||
return;
|
||||
}
|
||||
|
||||
denoiser_queue_->synchronize();
|
||||
}
|
||||
|
||||
void OptiXDenoiser::denoise_color_read(const DenoiseContext &context, const DenoisePass &pass)
|
||||
{
|
||||
PassAccessor::PassAccessInfo pass_access_info;
|
||||
pass_access_info.type = pass.type;
|
||||
pass_access_info.mode = PassMode::NOISY;
|
||||
pass_access_info.offset = pass.noisy_offset;
|
||||
|
||||
/* Denoiser operates on passes which are used to calculate the approximation, and is never used
|
||||
* on the approximation. The latter is not even possible because OptiX does not support
|
||||
* denoising of semi-transparent pixels. */
|
||||
pass_access_info.use_approximate_shadow_catcher = false;
|
||||
pass_access_info.use_approximate_shadow_catcher_background = false;
|
||||
pass_access_info.show_active_pixels = false;
|
||||
|
||||
/* TODO(sergey): Consider adding support of actual exposure, to avoid clamping in extreme cases.
|
||||
*/
|
||||
const PassAccessorGPU pass_accessor(
|
||||
denoiser_queue_.get(), pass_access_info, 1.0f, context.num_samples);
|
||||
|
||||
PassAccessor::Destination destination(pass_access_info.type);
|
||||
destination.d_pixels = context.render_buffers->buffer.device_pointer +
|
||||
pass.denoised_offset * sizeof(float);
|
||||
destination.num_components = 3;
|
||||
destination.pixel_stride = context.buffer_params.pass_stride;
|
||||
|
||||
BufferParams buffer_params = context.buffer_params;
|
||||
buffer_params.window_x = 0;
|
||||
buffer_params.window_y = 0;
|
||||
buffer_params.window_width = buffer_params.width;
|
||||
buffer_params.window_height = buffer_params.height;
|
||||
|
||||
pass_accessor.get_render_tile_pixels(context.render_buffers, buffer_params, destination);
|
||||
}
|
||||
|
||||
bool OptiXDenoiser::denoise_filter_color_preprocess(const DenoiseContext &context,
|
||||
const DenoisePass &pass)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const int work_size = buffer_params.width * buffer_params.height;
|
||||
|
||||
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
|
||||
&buffer_params.full_x,
|
||||
&buffer_params.full_y,
|
||||
&buffer_params.width,
|
||||
&buffer_params.height,
|
||||
&buffer_params.offset,
|
||||
&buffer_params.stride,
|
||||
&buffer_params.pass_stride,
|
||||
&pass.denoised_offset);
|
||||
|
||||
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_PREPROCESS, work_size, args);
|
||||
}
|
||||
|
||||
bool OptiXDenoiser::denoise_filter_color_postprocess(const DenoiseContext &context,
|
||||
const DenoisePass &pass)
|
||||
{
|
||||
const BufferParams &buffer_params = context.buffer_params;
|
||||
|
||||
const int work_size = buffer_params.width * buffer_params.height;
|
||||
|
||||
DeviceKernelArguments args(&context.render_buffers->buffer.device_pointer,
|
||||
&buffer_params.full_x,
|
||||
&buffer_params.full_y,
|
||||
&buffer_params.width,
|
||||
&buffer_params.height,
|
||||
&buffer_params.offset,
|
||||
&buffer_params.stride,
|
||||
&buffer_params.pass_stride,
|
||||
&context.num_samples,
|
||||
&pass.noisy_offset,
|
||||
&pass.denoised_offset,
|
||||
&context.pass_sample_count,
|
||||
&pass.num_components,
|
||||
&pass.use_compositing);
|
||||
|
||||
return denoiser_queue_->enqueue(DEVICE_KERNEL_FILTER_COLOR_POSTPROCESS, work_size, args);
|
||||
}
|
||||
|
||||
bool OptiXDenoiser::denoise_ensure(DenoiseContext &context)
|
||||
{
|
||||
if (!denoise_create_if_needed(context)) {
|
||||
|
|
|
@ -21,9 +21,6 @@ class OptiXDenoiser : public DenoiserGPU {
|
|||
virtual uint get_device_type_mask() const override;
|
||||
|
||||
private:
|
||||
class DenoiseContext;
|
||||
class DenoisePass;
|
||||
|
||||
virtual bool denoise_buffer(const DenoiseTask &task) override;
|
||||
|
||||
/* Read guiding passes from the render buffers, preprocess them in a way which is expected by
|
||||
|
@ -36,19 +33,6 @@ class OptiXDenoiser : public DenoiserGPU {
|
|||
/* Set fake albedo pixels in the albedo guiding pass storage.
|
||||
* After this point only passes which do not need albedo for denoising can be processed. */
|
||||
bool denoise_filter_guiding_set_fake_albedo(const DenoiseContext &context);
|
||||
|
||||
void denoise_pass(DenoiseContext &context, PassType pass_type);
|
||||
|
||||
/* Read input color pass from the render buffer into the memory which corresponds to the noisy
|
||||
* input within the given context. Pixels are scaled to the number of samples, but are not
|
||||
* preprocessed yet. */
|
||||
void denoise_color_read(const DenoiseContext &context, const DenoisePass &pass);
|
||||
|
||||
/* Run corresponding filter kernels, preparing data for the denoiser or copying data from the
|
||||
* denoiser result to the render buffer. */
|
||||
bool denoise_filter_color_preprocess(const DenoiseContext &context, const DenoisePass &pass);
|
||||
bool denoise_filter_color_postprocess(const DenoiseContext &context, const DenoisePass &pass);
|
||||
|
||||
/* Make sure the OptiX denoiser is created and configured. */
|
||||
bool denoise_ensure(DenoiseContext &context);
|
||||
|
||||
|
@ -61,7 +45,7 @@ class OptiXDenoiser : public DenoiserGPU {
|
|||
bool denoise_configure_if_needed(DenoiseContext &context);
|
||||
|
||||
/* Run configured denoiser. */
|
||||
bool denoise_run(const DenoiseContext &context, const DenoisePass &pass);
|
||||
bool denoise_run(const DenoiseContext &context, const DenoisePass &pass) override;
|
||||
|
||||
OptixDenoiser optix_denoiser_ = nullptr;
|
||||
|
||||
|
|
|
@ -109,6 +109,11 @@ class PassAccessor {
|
|||
/* Set pass data for the given render buffers. Used for baking to read from passes. */
|
||||
bool set_render_tile_pixels(RenderBuffers *render_buffers, const Source &source);
|
||||
|
||||
const PassAccessInfo &get_pass_access_info() const
|
||||
{
|
||||
return pass_access_info_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void init_kernel_film_convert(KernelFilmConvert *kfilm_convert,
|
||||
const BufferParams &buffer_params,
|
||||
|
|
|
@ -1036,7 +1036,12 @@ bool PathTrace::get_render_tile_pixels(const PassAccessor &pass_accessor,
|
|||
}
|
||||
|
||||
if (big_tile_denoise_work_ && render_state_.has_denoised_result) {
|
||||
return big_tile_denoise_work_->get_render_tile_pixels(pass_accessor, destination);
|
||||
/* Only use the big tile denoised buffer to access the denoised passes.
|
||||
* The guiding passes are allowed to be modified in-place for the needs of the denoiser,
|
||||
* so copy those from the original devices buffers. */
|
||||
if (pass_accessor.get_pass_access_info().mode == PassMode::DENOISED) {
|
||||
return big_tile_denoise_work_->get_render_tile_pixels(pass_accessor, destination);
|
||||
}
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
|
|
@ -362,7 +362,7 @@ void PathTraceWorkCPU::guiding_push_sample_data_to_global_storage(
|
|||
# endif
|
||||
|
||||
# ifdef WITH_CYCLES_DEBUG
|
||||
/* Check if the training/radiance samples generated py the path segment storage are valid.*/
|
||||
/* Check if the training/radiance samples generated by the path segment storage are valid. */
|
||||
if (VLOG_WORK_IS_ON) {
|
||||
const bool validSamples = kg->opgl_path_segment_storage->ValidateSamples();
|
||||
if (!validSamples) {
|
||||
|
|
|
@ -5,8 +5,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <embree3/rtcore_ray.h>
|
||||
#include <embree3/rtcore_scene.h>
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
# include <embree4/rtcore_ray.h>
|
||||
# include <embree4/rtcore_scene.h>
|
||||
#else
|
||||
# include <embree3/rtcore_ray.h>
|
||||
# include <embree3/rtcore_scene.h>
|
||||
#endif
|
||||
|
||||
#include "kernel/device/cpu/compat.h"
|
||||
#include "kernel/device/cpu/globals.h"
|
||||
|
@ -28,11 +33,84 @@ using numhit_t = uint8_t;
|
|||
using numhit_t = uint32_t;
|
||||
#endif
|
||||
|
||||
#define CYCLES_EMBREE_USED_FEATURES \
|
||||
(RTCFeatureFlags)(RTC_FEATURE_FLAG_TRIANGLE | RTC_FEATURE_FLAG_INSTANCE | \
|
||||
RTC_FEATURE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS | RTC_FEATURE_FLAG_POINT | \
|
||||
RTC_FEATURE_FLAG_MOTION_BLUR | RTC_FEATURE_FLAG_ROUND_CATMULL_ROM_CURVE | \
|
||||
RTC_FEATURE_FLAG_FLAT_CATMULL_ROM_CURVE)
|
||||
|
||||
#define EMBREE_IS_HAIR(x) (x & 1)
|
||||
|
||||
#if EMBREE_MAJOR_VERSION < 4
|
||||
# define rtcGetGeometryUserDataFromScene(scene, id) \
|
||||
(rtcGetGeometryUserData(rtcGetGeometry(scene, id)))
|
||||
#endif
|
||||
|
||||
/* Intersection context. */
|
||||
|
||||
struct CCLIntersectContext {
|
||||
struct CCLFirstHitContext
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
: public RTCRayQueryContext
|
||||
#endif
|
||||
{
|
||||
KernelGlobals kg;
|
||||
/* For avoiding self intersections */
|
||||
const Ray *ray;
|
||||
};
|
||||
|
||||
struct CCLShadowContext
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
: public RTCRayQueryContext
|
||||
#endif
|
||||
{
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
KernelGlobals kg;
|
||||
const Ray *ray;
|
||||
#endif
|
||||
IntegratorShadowState isect_s;
|
||||
float throughput;
|
||||
bool opaque_hit;
|
||||
numhit_t max_hits;
|
||||
numhit_t num_hits;
|
||||
numhit_t num_recorded_hits;
|
||||
};
|
||||
|
||||
struct CCLLocalContext
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
: public RTCRayQueryContext
|
||||
#endif
|
||||
{
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
KernelGlobals kg;
|
||||
const Ray *ray;
|
||||
numhit_t max_hits;
|
||||
#endif
|
||||
int local_object_id;
|
||||
LocalIntersection *local_isect;
|
||||
uint *lcg_state;
|
||||
bool is_sss;
|
||||
};
|
||||
|
||||
struct CCLVolumeContext
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
: public RTCRayQueryContext
|
||||
#endif
|
||||
{
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
KernelGlobals kg;
|
||||
const Ray *ray;
|
||||
numhit_t max_hits;
|
||||
numhit_t num_hits;
|
||||
#endif
|
||||
Intersection *vol_isect;
|
||||
};
|
||||
|
||||
#if EMBREE_MAJOR_VERSION < 4
|
||||
struct CCLIntersectContext : public RTCIntersectContext,
|
||||
public CCLFirstHitContext,
|
||||
public CCLShadowContext,
|
||||
public CCLLocalContext,
|
||||
public CCLVolumeContext {
|
||||
typedef enum {
|
||||
RAY_REGULAR = 0,
|
||||
RAY_SHADOW_ALL = 1,
|
||||
|
@ -41,28 +119,8 @@ struct CCLIntersectContext {
|
|||
RAY_VOLUME_ALL = 4,
|
||||
} RayType;
|
||||
|
||||
KernelGlobals kg;
|
||||
RayType type;
|
||||
|
||||
/* For avoiding self intersections */
|
||||
const Ray *ray;
|
||||
|
||||
/* for shadow rays */
|
||||
IntegratorShadowState isect_s;
|
||||
numhit_t max_hits;
|
||||
numhit_t num_hits;
|
||||
numhit_t num_recorded_hits;
|
||||
float throughput;
|
||||
bool opaque_hit;
|
||||
|
||||
/* for SSS Rays: */
|
||||
LocalIntersection *local_isect;
|
||||
int local_object_id;
|
||||
uint *lcg_state;
|
||||
|
||||
/* for Volume */
|
||||
Intersection *vol_isect;
|
||||
|
||||
CCLIntersectContext(KernelGlobals kg_, RayType type_)
|
||||
{
|
||||
kg = kg_;
|
||||
|
@ -79,17 +137,7 @@ struct CCLIntersectContext {
|
|||
lcg_state = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class IntersectContext {
|
||||
public:
|
||||
IntersectContext(CCLIntersectContext *ctx)
|
||||
{
|
||||
rtcInitIntersectContext(&context);
|
||||
userRayExt = ctx;
|
||||
}
|
||||
RTCIntersectContext context;
|
||||
CCLIntersectContext *userRayExt;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Utilities. */
|
||||
|
||||
|
@ -173,13 +221,12 @@ ccl_device_inline void kernel_embree_convert_hit(KernelGlobals kg,
|
|||
{
|
||||
intptr_t prim_offset;
|
||||
if (hit->instID[0] != RTC_INVALID_GEOMETRY_ID) {
|
||||
RTCScene inst_scene = (RTCScene)rtcGetGeometryUserData(
|
||||
rtcGetGeometry(kernel_data.device_bvh, hit->instID[0]));
|
||||
prim_offset = intptr_t(rtcGetGeometryUserData(rtcGetGeometry(inst_scene, hit->geomID)));
|
||||
RTCScene inst_scene = (RTCScene)rtcGetGeometryUserDataFromScene(kernel_data.device_bvh,
|
||||
hit->instID[0]);
|
||||
prim_offset = intptr_t(rtcGetGeometryUserDataFromScene(inst_scene, hit->geomID));
|
||||
}
|
||||
else {
|
||||
prim_offset = intptr_t(
|
||||
rtcGetGeometryUserData(rtcGetGeometry(kernel_data.device_bvh, hit->geomID)));
|
||||
prim_offset = intptr_t(rtcGetGeometryUserDataFromScene(kernel_data.device_bvh, hit->geomID));
|
||||
}
|
||||
kernel_embree_convert_hit(kg, ray, hit, isect, prim_offset);
|
||||
}
|
||||
|
@ -211,7 +258,11 @@ ccl_device void kernel_embree_filter_intersection_func(const RTCFilterFunctionNA
|
|||
assert(args->N == 1);
|
||||
|
||||
RTCHit *hit = (RTCHit *)args->hit;
|
||||
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLFirstHitContext *ctx = (CCLFirstHitContext *)(args->context);
|
||||
#else
|
||||
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
|
||||
#endif
|
||||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
const Ray *cray = ctx->ray;
|
||||
|
||||
|
@ -226,205 +277,257 @@ ccl_device void kernel_embree_filter_intersection_func(const RTCFilterFunctionNA
|
|||
* as well as filtering for volume objects happen here.
|
||||
* Cycles' own BVH does that directly inside the traversal calls.
|
||||
*/
|
||||
ccl_device void kernel_embree_filter_occluded_func(const RTCFilterFunctionNArguments *args)
|
||||
ccl_device void kernel_embree_filter_occluded_shadow_all_func(
|
||||
const RTCFilterFunctionNArguments *args)
|
||||
{
|
||||
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
||||
assert(args->N == 1);
|
||||
|
||||
RTCRay *ray = (RTCRay *)args->ray;
|
||||
RTCHit *hit = (RTCHit *)args->hit;
|
||||
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLShadowContext *ctx = (CCLShadowContext *)(args->context);
|
||||
#else
|
||||
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
|
||||
#endif
|
||||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
const Ray *cray = ctx->ray;
|
||||
|
||||
Intersection current_isect;
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (intersection_skip_self_shadow(cray->self, current_isect.object, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If no transparent shadows or max number of hits exceeded, all light is blocked. */
|
||||
const int flags = intersection_get_shader_flags(kg, current_isect.prim, current_isect.type);
|
||||
if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->num_hits >= ctx->max_hits) {
|
||||
ctx->opaque_hit = true;
|
||||
return;
|
||||
}
|
||||
|
||||
++ctx->num_hits;
|
||||
|
||||
/* Always use baked shadow transparency for curves. */
|
||||
if (current_isect.type & PRIMITIVE_CURVE) {
|
||||
ctx->throughput *= intersection_curve_shadow_transparency(
|
||||
kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u);
|
||||
|
||||
if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
|
||||
ctx->opaque_hit = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test if we need to record this transparent intersection. */
|
||||
const numhit_t max_record_hits = min(ctx->max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
|
||||
if (ctx->num_recorded_hits < max_record_hits) {
|
||||
/* If maximum number of hits was reached, replace the intersection with the
|
||||
* highest distance. We want to find the N closest intersections. */
|
||||
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
|
||||
numhit_t isect_index = num_recorded_hits;
|
||||
if (num_recorded_hits + 1 >= max_record_hits) {
|
||||
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
|
||||
numhit_t max_recorded_hit = numhit_t(0);
|
||||
|
||||
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
|
||||
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
|
||||
if (isect_t > max_t) {
|
||||
max_recorded_hit = i;
|
||||
max_t = isect_t;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_recorded_hits >= max_record_hits) {
|
||||
isect_index = max_recorded_hit;
|
||||
}
|
||||
|
||||
/* Limit the ray distance and stop counting hits beyond this. */
|
||||
ray->tfar = max(current_isect.t, max_t);
|
||||
}
|
||||
|
||||
integrator_state_write_shadow_isect(ctx->isect_s, ¤t_isect, isect_index);
|
||||
}
|
||||
|
||||
/* Always increase the number of recorded hits, even beyond the maximum,
|
||||
* so that we can detect this and trace another ray if needed. */
|
||||
++ctx->num_recorded_hits;
|
||||
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
}
|
||||
|
||||
ccl_device_forceinline void kernel_embree_filter_occluded_local_func(
|
||||
const RTCFilterFunctionNArguments *args)
|
||||
{
|
||||
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
||||
assert(args->N == 1);
|
||||
|
||||
const RTCRay *ray = (RTCRay *)args->ray;
|
||||
RTCHit *hit = (RTCHit *)args->hit;
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLLocalContext *ctx = (CCLLocalContext *)(args->context);
|
||||
#else
|
||||
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
|
||||
#endif
|
||||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
const Ray *cray = ctx->ray;
|
||||
|
||||
/* Check if it's hitting the correct object. */
|
||||
Intersection current_isect;
|
||||
if (ctx->is_sss) {
|
||||
kernel_embree_convert_sss_hit(kg,
|
||||
ray,
|
||||
hit,
|
||||
¤t_isect,
|
||||
ctx->local_object_id,
|
||||
reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
}
|
||||
else {
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (ctx->local_object_id != current_isect.object) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (intersection_skip_self_local(cray->self, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* No intersection information requested, just return a hit. */
|
||||
if (ctx->max_hits == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore curves. */
|
||||
if (EMBREE_IS_HAIR(hit->geomID)) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
LocalIntersection *local_isect = ctx->local_isect;
|
||||
int hit_idx = 0;
|
||||
|
||||
if (ctx->lcg_state) {
|
||||
/* See triangle_intersect_subsurface() for the native equivalent. */
|
||||
for (int i = min((int)ctx->max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
|
||||
if (local_isect->hits[i].t == ray->tfar) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
local_isect->num_hits++;
|
||||
|
||||
if (local_isect->num_hits <= ctx->max_hits) {
|
||||
hit_idx = local_isect->num_hits - 1;
|
||||
}
|
||||
else {
|
||||
/* reservoir sampling: if we are at the maximum number of
|
||||
* hits, randomly replace element or skip it */
|
||||
hit_idx = lcg_step_uint(ctx->lcg_state) % local_isect->num_hits;
|
||||
|
||||
if (hit_idx >= ctx->max_hits) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Record closest intersection only. */
|
||||
if (local_isect->num_hits && current_isect.t > local_isect->hits[0].t) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
local_isect->num_hits = 1;
|
||||
}
|
||||
|
||||
/* record intersection */
|
||||
local_isect->hits[hit_idx] = current_isect;
|
||||
local_isect->Ng[hit_idx] = normalize(make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z));
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
}
|
||||
|
||||
ccl_device_forceinline void kernel_embree_filter_occluded_volume_all_func(
|
||||
const RTCFilterFunctionNArguments *args)
|
||||
{
|
||||
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
||||
assert(args->N == 1);
|
||||
|
||||
const RTCRay *ray = (RTCRay *)args->ray;
|
||||
RTCHit *hit = (RTCHit *)args->hit;
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLVolumeContext *ctx = (CCLVolumeContext *)(args->context);
|
||||
#else
|
||||
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
|
||||
#endif
|
||||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
const Ray *cray = ctx->ray;
|
||||
|
||||
/* Append the intersection to the end of the array. */
|
||||
if (ctx->num_hits < ctx->max_hits) {
|
||||
Intersection current_isect;
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (intersection_skip_self(cray->self, current_isect.object, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Intersection *isect = &ctx->vol_isect[ctx->num_hits];
|
||||
++ctx->num_hits;
|
||||
*isect = current_isect;
|
||||
/* Only primitives from volume object. */
|
||||
uint tri_object = isect->object;
|
||||
int object_flag = kernel_data_fetch(object_flag, tri_object);
|
||||
if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
--ctx->num_hits;
|
||||
}
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if EMBREE_MAJOR_VERSION < 4
|
||||
ccl_device_forceinline void kernel_embree_filter_occluded_func(
|
||||
const RTCFilterFunctionNArguments *args)
|
||||
{
|
||||
/* Current implementation in Cycles assumes only single-ray intersection queries. */
|
||||
assert(args->N == 1);
|
||||
|
||||
CCLIntersectContext *ctx = (CCLIntersectContext *)(args->context);
|
||||
|
||||
switch (ctx->type) {
|
||||
case CCLIntersectContext::RAY_SHADOW_ALL: {
|
||||
Intersection current_isect;
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (intersection_skip_self_shadow(cray->self, current_isect.object, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
/* If no transparent shadows or max number of hits exceeded, all light is blocked. */
|
||||
const int flags = intersection_get_shader_flags(kg, current_isect.prim, current_isect.type);
|
||||
if (!(flags & (SD_HAS_TRANSPARENT_SHADOW)) || ctx->num_hits >= ctx->max_hits) {
|
||||
ctx->opaque_hit = true;
|
||||
return;
|
||||
}
|
||||
|
||||
++ctx->num_hits;
|
||||
|
||||
/* Always use baked shadow transparency for curves. */
|
||||
if (current_isect.type & PRIMITIVE_CURVE) {
|
||||
ctx->throughput *= intersection_curve_shadow_transparency(
|
||||
kg, current_isect.object, current_isect.prim, current_isect.type, current_isect.u);
|
||||
|
||||
if (ctx->throughput < CURVE_SHADOW_TRANSPARENCY_CUTOFF) {
|
||||
ctx->opaque_hit = true;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test if we need to record this transparent intersection. */
|
||||
const numhit_t max_record_hits = min(ctx->max_hits, INTEGRATOR_SHADOW_ISECT_SIZE);
|
||||
if (ctx->num_recorded_hits < max_record_hits) {
|
||||
/* If maximum number of hits was reached, replace the intersection with the
|
||||
* highest distance. We want to find the N closest intersections. */
|
||||
const numhit_t num_recorded_hits = min(ctx->num_recorded_hits, max_record_hits);
|
||||
numhit_t isect_index = num_recorded_hits;
|
||||
if (num_recorded_hits + 1 >= max_record_hits) {
|
||||
float max_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, 0, t);
|
||||
numhit_t max_recorded_hit = numhit_t(0);
|
||||
|
||||
for (numhit_t i = numhit_t(1); i < num_recorded_hits; ++i) {
|
||||
const float isect_t = INTEGRATOR_STATE_ARRAY(ctx->isect_s, shadow_isect, i, t);
|
||||
if (isect_t > max_t) {
|
||||
max_recorded_hit = i;
|
||||
max_t = isect_t;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_recorded_hits >= max_record_hits) {
|
||||
isect_index = max_recorded_hit;
|
||||
}
|
||||
|
||||
/* Limit the ray distance and stop counting hits beyond this. */
|
||||
ray->tfar = max(current_isect.t, max_t);
|
||||
}
|
||||
|
||||
integrator_state_write_shadow_isect(ctx->isect_s, ¤t_isect, isect_index);
|
||||
}
|
||||
|
||||
/* Always increase the number of recorded hits, even beyond the maximum,
|
||||
* so that we can detect this and trace another ray if needed. */
|
||||
++ctx->num_recorded_hits;
|
||||
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
case CCLIntersectContext::RAY_SHADOW_ALL:
|
||||
kernel_embree_filter_occluded_shadow_all_func(args);
|
||||
break;
|
||||
}
|
||||
case CCLIntersectContext::RAY_LOCAL:
|
||||
case CCLIntersectContext::RAY_SSS: {
|
||||
/* Check if it's hitting the correct object. */
|
||||
Intersection current_isect;
|
||||
if (ctx->type == CCLIntersectContext::RAY_SSS) {
|
||||
kernel_embree_convert_sss_hit(kg,
|
||||
ray,
|
||||
hit,
|
||||
¤t_isect,
|
||||
ctx->local_object_id,
|
||||
reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
}
|
||||
else {
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (ctx->local_object_id != current_isect.object) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (intersection_skip_self_local(cray->self, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* No intersection information requested, just return a hit. */
|
||||
if (ctx->max_hits == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Ignore curves. */
|
||||
if (EMBREE_IS_HAIR(hit->geomID)) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
LocalIntersection *local_isect = ctx->local_isect;
|
||||
int hit_idx = 0;
|
||||
|
||||
if (ctx->lcg_state) {
|
||||
/* See triangle_intersect_subsurface() for the native equivalent. */
|
||||
for (int i = min((int)ctx->max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
|
||||
if (local_isect->hits[i].t == ray->tfar) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
local_isect->num_hits++;
|
||||
|
||||
if (local_isect->num_hits <= ctx->max_hits) {
|
||||
hit_idx = local_isect->num_hits - 1;
|
||||
}
|
||||
else {
|
||||
/* reservoir sampling: if we are at the maximum number of
|
||||
* hits, randomly replace element or skip it */
|
||||
hit_idx = lcg_step_uint(ctx->lcg_state) % local_isect->num_hits;
|
||||
|
||||
if (hit_idx >= ctx->max_hits) {
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Record closest intersection only. */
|
||||
if (local_isect->num_hits && current_isect.t > local_isect->hits[0].t) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
local_isect->num_hits = 1;
|
||||
}
|
||||
|
||||
/* record intersection */
|
||||
local_isect->hits[hit_idx] = current_isect;
|
||||
local_isect->Ng[hit_idx] = normalize(make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z));
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
case CCLIntersectContext::RAY_SSS:
|
||||
kernel_embree_filter_occluded_local_func(args);
|
||||
break;
|
||||
}
|
||||
case CCLIntersectContext::RAY_VOLUME_ALL: {
|
||||
/* Append the intersection to the end of the array. */
|
||||
if (ctx->num_hits < ctx->max_hits) {
|
||||
Intersection current_isect;
|
||||
kernel_embree_convert_hit(
|
||||
kg, ray, hit, ¤t_isect, reinterpret_cast<intptr_t>(args->geometryUserPtr));
|
||||
if (intersection_skip_self(cray->self, current_isect.object, current_isect.prim)) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Intersection *isect = &ctx->vol_isect[ctx->num_hits];
|
||||
++ctx->num_hits;
|
||||
*isect = current_isect;
|
||||
/* Only primitives from volume object. */
|
||||
uint tri_object = isect->object;
|
||||
int object_flag = kernel_data_fetch(object_flag, tri_object);
|
||||
if ((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
|
||||
--ctx->num_hits;
|
||||
}
|
||||
/* This tells Embree to continue tracing. */
|
||||
*args->valid = 0;
|
||||
}
|
||||
case CCLIntersectContext::RAY_VOLUME_ALL:
|
||||
kernel_embree_filter_occluded_volume_all_func(args);
|
||||
break;
|
||||
}
|
||||
|
||||
case CCLIntersectContext::RAY_REGULAR:
|
||||
default:
|
||||
if (kernel_embree_is_self_intersection(
|
||||
kg, hit, cray, reinterpret_cast<intptr_t>(args->geometryUserPtr))) {
|
||||
*args->valid = 0;
|
||||
return;
|
||||
}
|
||||
/* We should never reach this point, because
|
||||
* REGULAR intersection is handled in intersection filter. */
|
||||
kernel_assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +544,7 @@ ccl_device void kernel_embree_filter_func_backface_cull(const RTCFilterFunctionN
|
|||
return;
|
||||
}
|
||||
|
||||
CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt;
|
||||
CCLIntersectContext *ctx = ((CCLIntersectContext *)args->context);
|
||||
const KernelGlobalsCPU *kg = ctx->kg;
|
||||
const Ray *cray = ctx->ray;
|
||||
|
||||
|
@ -467,6 +570,8 @@ ccl_device void kernel_embree_filter_occluded_func_backface_cull(
|
|||
kernel_embree_filter_occluded_func(args);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Scene intersection. */
|
||||
|
||||
ccl_device_intersect bool kernel_embree_intersect(KernelGlobals kg,
|
||||
|
@ -475,12 +580,29 @@ ccl_device_intersect bool kernel_embree_intersect(KernelGlobals kg,
|
|||
ccl_private Intersection *isect)
|
||||
{
|
||||
isect->t = ray->tmax;
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLFirstHitContext ctx;
|
||||
rtcInitRayQueryContext(&ctx);
|
||||
ctx.kg = kg;
|
||||
#else
|
||||
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_REGULAR);
|
||||
IntersectContext rtc_ctx(&ctx);
|
||||
rtcInitIntersectContext(&ctx);
|
||||
#endif
|
||||
|
||||
RTCRayHit ray_hit;
|
||||
ctx.ray = ray;
|
||||
kernel_embree_setup_rayhit(*ray, ray_hit, visibility);
|
||||
rtcIntersect1(kernel_data.device_bvh, &rtc_ctx.context, &ray_hit);
|
||||
|
||||
#if EMBREE_MAJOR_VERSION >= 4
|
||||
RTCIntersectArguments args;
|
||||
rtcInitIntersectArguments(&args);
|
||||
args.filter = (RTCFilterFunctionN)kernel_embree_filter_intersection_func;
|
||||
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
|
||||
args.context = &ctx;
|
||||
rtcIntersect1(kernel_data.device_bvh, &ray_hit, &args);
|
||||
#else
|
||||
rtcIntersect1(kernel_data.device_bvh, &ctx, &ray_hit);
|
||||
#endif
|
||||
if (ray_hit.hit.geomID == RTC_INVALID_GEOMETRY_ID ||
|
||||
ray_hit.hit.primID == RTC_INVALID_GEOMETRY_ID) {
|
||||
return false;
|
||||
|
@ -500,8 +622,16 @@ ccl_device_intersect bool kernel_embree_intersect_local(KernelGlobals kg,
|
|||
{
|
||||
const bool has_bvh = !(kernel_data_fetch(object_flag, local_object) &
|
||||
SD_OBJECT_TRANSFORM_APPLIED);
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLLocalContext ctx;
|
||||
rtcInitRayQueryContext(&ctx);
|
||||
ctx.kg = kg;
|
||||
# else
|
||||
CCLIntersectContext ctx(kg,
|
||||
has_bvh ? CCLIntersectContext::RAY_SSS : CCLIntersectContext::RAY_LOCAL);
|
||||
rtcInitIntersectContext(&ctx);
|
||||
# endif
|
||||
ctx.is_sss = has_bvh;
|
||||
ctx.lcg_state = lcg_state;
|
||||
ctx.max_hits = max_hits;
|
||||
ctx.ray = ray;
|
||||
|
@ -510,36 +640,49 @@ ccl_device_intersect bool kernel_embree_intersect_local(KernelGlobals kg,
|
|||
local_isect->num_hits = 0;
|
||||
}
|
||||
ctx.local_object_id = local_object;
|
||||
IntersectContext rtc_ctx(&ctx);
|
||||
RTCRay rtc_ray;
|
||||
kernel_embree_setup_ray(*ray, rtc_ray, PATH_RAY_ALL_VISIBILITY);
|
||||
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
RTCOccludedArguments args;
|
||||
rtcInitOccludedArguments(&args);
|
||||
args.filter = (RTCFilterFunctionN)(kernel_embree_filter_occluded_local_func);
|
||||
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
|
||||
args.context = &ctx;
|
||||
# endif
|
||||
|
||||
/* If this object has its own BVH, use it. */
|
||||
if (has_bvh) {
|
||||
RTCGeometry geom = rtcGetGeometry(kernel_data.device_bvh, local_object * 2);
|
||||
if (geom) {
|
||||
float3 P = ray->P;
|
||||
float3 dir = ray->D;
|
||||
float3 idir = ray->D;
|
||||
bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir);
|
||||
float3 P = ray->P;
|
||||
float3 dir = ray->D;
|
||||
float3 idir = ray->D;
|
||||
bvh_instance_motion_push(kg, local_object, ray, &P, &dir, &idir);
|
||||
|
||||
rtc_ray.org_x = P.x;
|
||||
rtc_ray.org_y = P.y;
|
||||
rtc_ray.org_z = P.z;
|
||||
rtc_ray.dir_x = dir.x;
|
||||
rtc_ray.dir_y = dir.y;
|
||||
rtc_ray.dir_z = dir.z;
|
||||
rtc_ray.tnear = ray->tmin;
|
||||
rtc_ray.tfar = ray->tmax;
|
||||
RTCScene scene = (RTCScene)rtcGetGeometryUserData(geom);
|
||||
kernel_assert(scene);
|
||||
if (scene) {
|
||||
rtcOccluded1(scene, &rtc_ctx.context, &rtc_ray);
|
||||
}
|
||||
rtc_ray.org_x = P.x;
|
||||
rtc_ray.org_y = P.y;
|
||||
rtc_ray.org_z = P.z;
|
||||
rtc_ray.dir_x = dir.x;
|
||||
rtc_ray.dir_y = dir.y;
|
||||
rtc_ray.dir_z = dir.z;
|
||||
rtc_ray.tnear = ray->tmin;
|
||||
rtc_ray.tfar = ray->tmax;
|
||||
RTCScene scene = (RTCScene)rtcGetGeometryUserDataFromScene(kernel_data.device_bvh,
|
||||
local_object * 2);
|
||||
kernel_assert(scene);
|
||||
if (scene) {
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
rtcOccluded1(scene, &rtc_ray, &args);
|
||||
# else
|
||||
rtcOccluded1(scene, &ctx, &rtc_ray);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
rtcOccluded1(kernel_data.device_bvh, &rtc_ctx.context, &rtc_ray);
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
rtcOccluded1(kernel_data.device_bvh, &rtc_ray, &args);
|
||||
# else
|
||||
rtcOccluded1(kernel_data.device_bvh, &ctx, &rtc_ray);
|
||||
# endif
|
||||
}
|
||||
|
||||
/* rtcOccluded1 sets tfar to -inf if a hit was found. */
|
||||
|
@ -556,14 +699,32 @@ ccl_device_intersect bool kernel_embree_intersect_shadow_all(KernelGlobals kg,
|
|||
ccl_private uint *num_recorded_hits,
|
||||
ccl_private float *throughput)
|
||||
{
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLShadowContext ctx;
|
||||
rtcInitRayQueryContext(&ctx);
|
||||
ctx.kg = kg;
|
||||
# else
|
||||
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_SHADOW_ALL);
|
||||
rtcInitIntersectContext(&ctx);
|
||||
# endif
|
||||
ctx.num_hits = ctx.num_recorded_hits = numhit_t(0);
|
||||
ctx.throughput = 1.0f;
|
||||
ctx.opaque_hit = false;
|
||||
ctx.isect_s = state;
|
||||
ctx.max_hits = numhit_t(max_hits);
|
||||
ctx.ray = ray;
|
||||
IntersectContext rtc_ctx(&ctx);
|
||||
RTCRay rtc_ray;
|
||||
kernel_embree_setup_ray(*ray, rtc_ray, visibility);
|
||||
rtcOccluded1(kernel_data.device_bvh, &rtc_ctx.context, &rtc_ray);
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
RTCOccludedArguments args;
|
||||
rtcInitOccludedArguments(&args);
|
||||
args.filter = (RTCFilterFunctionN)kernel_embree_filter_occluded_shadow_all_func;
|
||||
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
|
||||
args.context = &ctx;
|
||||
rtcOccluded1(kernel_data.device_bvh, &rtc_ray, &args);
|
||||
# else
|
||||
rtcOccluded1(kernel_data.device_bvh, &ctx, &rtc_ray);
|
||||
# endif
|
||||
|
||||
*num_recorded_hits = ctx.num_recorded_hits;
|
||||
*throughput = ctx.throughput;
|
||||
|
@ -578,15 +739,30 @@ ccl_device_intersect uint kernel_embree_intersect_volume(KernelGlobals kg,
|
|||
const uint max_hits,
|
||||
const uint visibility)
|
||||
{
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
CCLVolumeContext ctx;
|
||||
rtcInitRayQueryContext(&ctx);
|
||||
ctx.kg = kg;
|
||||
# else
|
||||
CCLIntersectContext ctx(kg, CCLIntersectContext::RAY_VOLUME_ALL);
|
||||
rtcInitIntersectContext(&ctx);
|
||||
# endif
|
||||
ctx.vol_isect = isect;
|
||||
ctx.max_hits = numhit_t(max_hits);
|
||||
ctx.num_hits = numhit_t(0);
|
||||
ctx.ray = ray;
|
||||
IntersectContext rtc_ctx(&ctx);
|
||||
RTCRay rtc_ray;
|
||||
kernel_embree_setup_ray(*ray, rtc_ray, visibility);
|
||||
rtcOccluded1(kernel_data.device_bvh, &rtc_ctx.context, &rtc_ray);
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
RTCOccludedArguments args;
|
||||
rtcInitOccludedArguments(&args);
|
||||
args.filter = (RTCFilterFunctionN)kernel_embree_filter_occluded_volume_all_func;
|
||||
args.feature_mask = CYCLES_EMBREE_USED_FEATURES;
|
||||
args.context = &ctx;
|
||||
rtcOccluded1(kernel_data.device_bvh, &rtc_ray, &args);
|
||||
# else
|
||||
rtcOccluded1(kernel_data.device_bvh, &ctx, &rtc_ray);
|
||||
# endif
|
||||
return ctx.num_hits;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -74,57 +74,43 @@ ccl_device_inline void motion_triangle_normals_for_step(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
ccl_device_inline void motion_triangle_vertices(
|
||||
KernelGlobals kg, int object, int prim, float time, float3 verts[3])
|
||||
ccl_device_inline void motion_triangle_compute_info(KernelGlobals kg,
|
||||
int object,
|
||||
float time,
|
||||
int prim,
|
||||
ccl_private uint3 *tri_vindex,
|
||||
ccl_private int *numsteps,
|
||||
ccl_private int *numverts,
|
||||
ccl_private int *step,
|
||||
ccl_private float *t)
|
||||
{
|
||||
/* get motion info */
|
||||
int numsteps, numverts;
|
||||
object_motion_info(kg, object, &numsteps, &numverts, NULL);
|
||||
|
||||
/* figure out which steps we need to fetch and their interpolation factor */
|
||||
int maxstep = numsteps * 2;
|
||||
int step = min((int)(time * maxstep), maxstep - 1);
|
||||
float t = time * maxstep - step;
|
||||
|
||||
/* find attribute */
|
||||
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
|
||||
/* fetch vertex coordinates */
|
||||
float3 next_verts[3];
|
||||
|
||||
uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
|
||||
|
||||
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
|
||||
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
|
||||
|
||||
/* interpolate between steps */
|
||||
verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
|
||||
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
|
||||
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
|
||||
}
|
||||
|
||||
ccl_device_inline void motion_triangle_vertices_and_normals(
|
||||
KernelGlobals kg, int object, int prim, float time, float3 verts[3], float3 normals[3])
|
||||
{
|
||||
/* get motion info */
|
||||
int numsteps, numverts;
|
||||
object_motion_info(kg, object, &numsteps, &numverts, NULL);
|
||||
/* Get object motion info. */
|
||||
object_motion_info(kg, object, numsteps, numverts, NULL);
|
||||
|
||||
/* Figure out which steps we need to fetch and their interpolation factor. */
|
||||
int maxstep = numsteps * 2;
|
||||
int step = min((int)(time * maxstep), maxstep - 1);
|
||||
float t = time * maxstep - step;
|
||||
int maxstep = *numsteps * 2;
|
||||
*step = min((int)(time * maxstep), maxstep - 1);
|
||||
*t = time * maxstep - *step;
|
||||
|
||||
/* Get triangle indices. */
|
||||
*tri_vindex = kernel_data_fetch(tri_vindex, prim);
|
||||
}
|
||||
|
||||
ccl_device_inline void motion_triangle_vertices(KernelGlobals kg,
|
||||
int object,
|
||||
uint3 tri_vindex,
|
||||
int numsteps,
|
||||
int numverts,
|
||||
int step,
|
||||
float t,
|
||||
float3 verts[3])
|
||||
{
|
||||
/* Find attribute. */
|
||||
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
|
||||
/* Fetch vertex coordinates. */
|
||||
float3 next_verts[3];
|
||||
|
||||
uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
|
||||
|
||||
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
|
||||
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
|
||||
|
||||
|
@ -132,60 +118,90 @@ ccl_device_inline void motion_triangle_vertices_and_normals(
|
|||
verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
|
||||
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
|
||||
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
|
||||
}
|
||||
|
||||
/* Compute smooth normal. */
|
||||
ccl_device_inline void motion_triangle_vertices(
|
||||
KernelGlobals kg, int object, int prim, float time, float3 verts[3])
|
||||
{
|
||||
int numsteps, numverts, step;
|
||||
float t;
|
||||
uint3 tri_vindex;
|
||||
motion_triangle_compute_info(
|
||||
kg, object, time, prim, &tri_vindex, &numsteps, &numverts, &step, &t);
|
||||
|
||||
motion_triangle_vertices(kg, object, tri_vindex, numsteps, numverts, step, t, verts);
|
||||
}
|
||||
|
||||
ccl_device_inline void motion_triangle_normals(KernelGlobals kg,
|
||||
int object,
|
||||
uint3 tri_vindex,
|
||||
int numsteps,
|
||||
int numverts,
|
||||
int step,
|
||||
float t,
|
||||
float3 normals[3])
|
||||
{
|
||||
/* Find attribute. */
|
||||
offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL);
|
||||
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
|
||||
/* Fetch vertex coordinates. */
|
||||
/* Fetch normals. */
|
||||
float3 next_normals[3];
|
||||
motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
|
||||
motion_triangle_normals_for_step(
|
||||
kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
|
||||
|
||||
/* Interpolate between steps. */
|
||||
normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
|
||||
normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
|
||||
normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
|
||||
normals[0] = normalize((1.0f - t) * normals[0] + t * next_normals[0]);
|
||||
normals[1] = normalize((1.0f - t) * normals[1] + t * next_normals[1]);
|
||||
normals[2] = normalize((1.0f - t) * normals[2] + t * next_normals[2]);
|
||||
}
|
||||
|
||||
ccl_device_inline void motion_triangle_vertices_and_normals(
|
||||
KernelGlobals kg, int object, int prim, float time, float3 verts[3], float3 normals[3])
|
||||
{
|
||||
int numsteps, numverts, step;
|
||||
float t;
|
||||
uint3 tri_vindex;
|
||||
motion_triangle_compute_info(
|
||||
kg, object, time, prim, &tri_vindex, &numsteps, &numverts, &step, &t);
|
||||
|
||||
motion_triangle_vertices(kg, object, tri_vindex, numsteps, numverts, step, t, verts);
|
||||
motion_triangle_normals(kg, object, tri_vindex, numsteps, numverts, step, t, normals);
|
||||
}
|
||||
|
||||
ccl_device_inline float3 motion_triangle_smooth_normal(KernelGlobals kg,
|
||||
float3 Ng,
|
||||
int object,
|
||||
uint3 tri_vindex,
|
||||
int numsteps,
|
||||
int numverts,
|
||||
int step,
|
||||
float t,
|
||||
float u,
|
||||
float v)
|
||||
{
|
||||
float3 normals[3];
|
||||
motion_triangle_normals(kg, object, tri_vindex, numsteps, numverts, step, t, normals);
|
||||
|
||||
/* Interpolate between normals. */
|
||||
float w = 1.0f - u - v;
|
||||
float3 N = safe_normalize(w * normals[0] + u * normals[1] + v * normals[2]);
|
||||
|
||||
return is_zero(N) ? Ng : N;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 motion_triangle_smooth_normal(
|
||||
KernelGlobals kg, float3 Ng, int object, int prim, float u, float v, float time)
|
||||
{
|
||||
/* get motion info */
|
||||
int numsteps, numverts;
|
||||
object_motion_info(kg, object, &numsteps, &numverts, NULL);
|
||||
int numsteps, numverts, step;
|
||||
float t;
|
||||
uint3 tri_vindex;
|
||||
motion_triangle_compute_info(
|
||||
kg, object, time, prim, &tri_vindex, &numsteps, &numverts, &step, &t);
|
||||
|
||||
/* figure out which steps we need to fetch and their interpolation factor */
|
||||
int maxstep = numsteps * 2;
|
||||
int step = min((int)(time * maxstep), maxstep - 1);
|
||||
float t = time * maxstep - step;
|
||||
|
||||
/* find attribute */
|
||||
int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_NORMAL);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
|
||||
/* fetch normals */
|
||||
float3 normals[3], next_normals[3];
|
||||
|
||||
uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
|
||||
|
||||
motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
|
||||
motion_triangle_normals_for_step(
|
||||
kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
|
||||
|
||||
/* interpolate between steps */
|
||||
normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
|
||||
normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
|
||||
normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
|
||||
|
||||
/* interpolate between vertices */
|
||||
float w = 1.0f - u - v;
|
||||
float3 N = safe_normalize(u * normals[0] + v * normals[1] + w * normals[2]);
|
||||
|
||||
return is_zero(N) ? Ng : N;
|
||||
return motion_triangle_smooth_normal(
|
||||
kg, Ng, object, tri_vindex, numsteps, numverts, step, t, u, v);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
@ -32,30 +32,17 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
|
|||
{
|
||||
/* Get shader. */
|
||||
sd->shader = kernel_data_fetch(tri_shader, sd->prim);
|
||||
/* Get motion info. */
|
||||
/* TODO(sergey): This logic is really similar to motion_triangle_vertices(),
|
||||
* can we de-duplicate something here?
|
||||
*/
|
||||
int numsteps, numverts;
|
||||
object_motion_info(kg, sd->object, &numsteps, &numverts, NULL);
|
||||
/* Figure out which steps we need to fetch and their interpolation factor. */
|
||||
int maxstep = numsteps * 2;
|
||||
int step = min((int)(sd->time * maxstep), maxstep - 1);
|
||||
float t = sd->time * maxstep - step;
|
||||
/* Find attribute. */
|
||||
int offset = intersection_find_attribute(kg, sd->object, ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
/* Fetch vertex coordinates. */
|
||||
float3 verts[3], next_verts[3];
|
||||
|
||||
uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
|
||||
/* Compute motion info. */
|
||||
int numsteps, numverts, step;
|
||||
float t;
|
||||
uint3 tri_vindex;
|
||||
motion_triangle_compute_info(
|
||||
kg, sd->object, sd->time, sd->prim, &tri_vindex, &numsteps, &numverts, &step, &t);
|
||||
|
||||
float3 verts[3];
|
||||
motion_triangle_vertices(kg, sd->object, tri_vindex, numsteps, numverts, step, t, verts);
|
||||
|
||||
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
|
||||
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step + 1, next_verts);
|
||||
/* Interpolate between steps. */
|
||||
verts[0] = (1.0f - t) * verts[0] + t * next_verts[0];
|
||||
verts[1] = (1.0f - t) * verts[1] + t * next_verts[1];
|
||||
verts[2] = (1.0f - t) * verts[2] + t * next_verts[2];
|
||||
/* Compute refined position. */
|
||||
sd->P = motion_triangle_point_from_uv(kg, sd, isect_object, isect_prim, sd->u, sd->v, verts);
|
||||
/* Compute face normal. */
|
||||
|
@ -75,23 +62,8 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals kg,
|
|||
#endif
|
||||
/* Compute smooth normal. */
|
||||
if (sd->shader & SHADER_SMOOTH_NORMAL) {
|
||||
/* Find attribute. */
|
||||
int offset = intersection_find_attribute(kg, sd->object, ATTR_STD_MOTION_VERTEX_NORMAL);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
/* Fetch vertex coordinates. */
|
||||
float3 normals[3], next_normals[3];
|
||||
motion_triangle_normals_for_step(kg, tri_vindex, offset, numverts, numsteps, step, normals);
|
||||
motion_triangle_normals_for_step(
|
||||
kg, tri_vindex, offset, numverts, numsteps, step + 1, next_normals);
|
||||
/* Interpolate between steps. */
|
||||
normals[0] = (1.0f - t) * normals[0] + t * next_normals[0];
|
||||
normals[1] = (1.0f - t) * normals[1] + t * next_normals[1];
|
||||
normals[2] = (1.0f - t) * normals[2] + t * next_normals[2];
|
||||
/* Interpolate between vertices. */
|
||||
float u = sd->u;
|
||||
float v = sd->v;
|
||||
float w = 1.0f - u - v;
|
||||
sd->N = (w * normals[0] + u * normals[1] + v * normals[2]);
|
||||
sd->N = motion_triangle_smooth_normal(
|
||||
kg, Ng, sd->object, tri_vindex, numsteps, numverts, step, t, sd->u, sd->v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ ccl_device_noinline int svm_node_tex_coord(KernelGlobals kg,
|
|||
uint4 node,
|
||||
int offset)
|
||||
{
|
||||
float3 data;
|
||||
float3 data = zero_float3();
|
||||
uint type = node.y;
|
||||
uint out_offset = node.z;
|
||||
|
||||
|
@ -100,7 +100,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dx(KernelGlobals kg,
|
|||
int offset)
|
||||
{
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
float3 data;
|
||||
float3 data = zero_float3();
|
||||
uint type = node.y;
|
||||
uint out_offset = node.z;
|
||||
|
||||
|
@ -185,7 +185,7 @@ ccl_device_noinline int svm_node_tex_coord_bump_dy(KernelGlobals kg,
|
|||
int offset)
|
||||
{
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
float3 data;
|
||||
float3 data = zero_float3();
|
||||
uint type = node.y;
|
||||
uint out_offset = node.z;
|
||||
|
||||
|
|
|
@ -4,8 +4,13 @@
|
|||
#pragma once
|
||||
|
||||
#if !defined(__KERNEL_GPU__) && defined(WITH_EMBREE)
|
||||
# include <embree3/rtcore.h>
|
||||
# include <embree3/rtcore_scene.h>
|
||||
# if EMBREE_MAJOR_VERSION >= 4
|
||||
# include <embree4/rtcore.h>
|
||||
# include <embree4/rtcore_scene.h>
|
||||
# else
|
||||
# include <embree3/rtcore.h>
|
||||
# include <embree3/rtcore_scene.h>
|
||||
# endif
|
||||
# define __EMBREE__
|
||||
#endif
|
||||
|
||||
|
|
|
@ -247,13 +247,16 @@ size_t CachedData::memory_used() const
|
|||
static M44d convert_yup_zup(const M44d &mtx, float scale_mult)
|
||||
{
|
||||
V3d scale, shear, rotation, translation;
|
||||
extractSHRT(mtx,
|
||||
scale,
|
||||
shear,
|
||||
rotation,
|
||||
translation,
|
||||
true,
|
||||
IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY);
|
||||
|
||||
if (!extractSHRT(mtx,
|
||||
scale,
|
||||
shear,
|
||||
rotation,
|
||||
translation,
|
||||
true,
|
||||
IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY)) {
|
||||
return mtx;
|
||||
}
|
||||
|
||||
M44d rot_mat, scale_mat, trans_mat;
|
||||
rot_mat.setEulerAngles(V3d(rotation.x, -rotation.z, rotation.y));
|
||||
|
|
|
@ -531,7 +531,7 @@ PrimitiveType Hair::primitive_type() const
|
|||
|
||||
/* Fill in coordinates for curve transparency shader evaluation on device. */
|
||||
static int fill_shader_input(const Hair *hair,
|
||||
const int object_index,
|
||||
const size_t object_index,
|
||||
device_vector<KernelShaderEvalInput> &d_input)
|
||||
{
|
||||
int d_input_size = 0;
|
||||
|
|
|
@ -86,7 +86,7 @@ ImageHandle::ImageHandle(const ImageHandle &other)
|
|||
: tile_slots(other.tile_slots), manager(other.manager)
|
||||
{
|
||||
/* Increase image user count. */
|
||||
foreach (const int slot, tile_slots) {
|
||||
foreach (const size_t slot, tile_slots) {
|
||||
manager->add_image_user(slot);
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ ImageHandle &ImageHandle::operator=(const ImageHandle &other)
|
|||
manager = other.manager;
|
||||
tile_slots = other.tile_slots;
|
||||
|
||||
foreach (const int slot, tile_slots) {
|
||||
foreach (const size_t slot, tile_slots) {
|
||||
manager->add_image_user(slot);
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ ImageHandle::~ImageHandle()
|
|||
|
||||
void ImageHandle::clear()
|
||||
{
|
||||
foreach (const int slot, tile_slots) {
|
||||
foreach (const size_t slot, tile_slots) {
|
||||
manager->remove_image_user(slot);
|
||||
}
|
||||
|
||||
|
@ -165,7 +165,7 @@ vector<int4> ImageHandle::get_svm_slots() const
|
|||
for (size_t i = 0; i < num_nodes; i++) {
|
||||
int4 node;
|
||||
|
||||
int slot = tile_slots[2 * i];
|
||||
size_t slot = tile_slots[2 * i];
|
||||
node.x = manager->images[slot]->loader->get_tile_number();
|
||||
node.y = slot;
|
||||
|
||||
|
@ -387,7 +387,7 @@ void ImageManager::load_image_metadata(Image *img)
|
|||
|
||||
ImageHandle ImageManager::add_image(const string &filename, const ImageParams ¶ms)
|
||||
{
|
||||
const int slot = add_image_slot(new OIIOImageLoader(filename), params, false);
|
||||
const size_t slot = add_image_slot(new OIIOImageLoader(filename), params, false);
|
||||
|
||||
ImageHandle handle;
|
||||
handle.tile_slots.push_back(slot);
|
||||
|
@ -408,13 +408,13 @@ ImageHandle ImageManager::add_image(const string &filename,
|
|||
/* Since we don't have information about the exact tile format used in this code location,
|
||||
* just attempt all replacement patterns that Blender supports. */
|
||||
if (tile != 0) {
|
||||
string_replace(tile_filename, "<UDIM>", string_printf("%04d", tile));
|
||||
string_replace(tile_filename, "<UDIM>", string_printf("%04d", (int)tile));
|
||||
|
||||
int u = ((tile - 1001) % 10);
|
||||
int v = ((tile - 1001) / 10);
|
||||
string_replace(tile_filename, "<UVTILE>", string_printf("u%d_v%d", u + 1, v + 1));
|
||||
}
|
||||
const int slot = add_image_slot(new OIIOImageLoader(tile_filename), params, false);
|
||||
const size_t slot = add_image_slot(new OIIOImageLoader(tile_filename), params, false);
|
||||
handle.tile_slots.push_back(slot);
|
||||
}
|
||||
|
||||
|
@ -425,7 +425,7 @@ ImageHandle ImageManager::add_image(ImageLoader *loader,
|
|||
const ImageParams ¶ms,
|
||||
const bool builtin)
|
||||
{
|
||||
const int slot = add_image_slot(loader, params, builtin);
|
||||
const size_t slot = add_image_slot(loader, params, builtin);
|
||||
|
||||
ImageHandle handle;
|
||||
handle.tile_slots.push_back(slot);
|
||||
|
@ -438,7 +438,7 @@ ImageHandle ImageManager::add_image(const vector<ImageLoader *> &loaders,
|
|||
{
|
||||
ImageHandle handle;
|
||||
for (ImageLoader *loader : loaders) {
|
||||
const int slot = add_image_slot(loader, params, true);
|
||||
const size_t slot = add_image_slot(loader, params, true);
|
||||
handle.tile_slots.push_back(slot);
|
||||
}
|
||||
|
||||
|
@ -446,9 +446,9 @@ ImageHandle ImageManager::add_image(const vector<ImageLoader *> &loaders,
|
|||
return handle;
|
||||
}
|
||||
|
||||
int ImageManager::add_image_slot(ImageLoader *loader,
|
||||
const ImageParams ¶ms,
|
||||
const bool builtin)
|
||||
size_t ImageManager::add_image_slot(ImageLoader *loader,
|
||||
const ImageParams ¶ms,
|
||||
const bool builtin)
|
||||
{
|
||||
Image *img;
|
||||
size_t slot;
|
||||
|
@ -492,7 +492,7 @@ int ImageManager::add_image_slot(ImageLoader *loader,
|
|||
return slot;
|
||||
}
|
||||
|
||||
void ImageManager::add_image_user(int slot)
|
||||
void ImageManager::add_image_user(size_t slot)
|
||||
{
|
||||
thread_scoped_lock device_lock(images_mutex);
|
||||
Image *image = images[slot];
|
||||
|
@ -501,7 +501,7 @@ void ImageManager::add_image_user(int slot)
|
|||
image->users++;
|
||||
}
|
||||
|
||||
void ImageManager::remove_image_user(int slot)
|
||||
void ImageManager::remove_image_user(size_t slot)
|
||||
{
|
||||
thread_scoped_lock device_lock(images_mutex);
|
||||
Image *image = images[slot];
|
||||
|
@ -682,7 +682,7 @@ bool ImageManager::file_load_image(Image *img, int texture_limit)
|
|||
return true;
|
||||
}
|
||||
|
||||
void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Progress *progress)
|
||||
void ImageManager::device_load_image(Device *device, Scene *scene, size_t slot, Progress *progress)
|
||||
{
|
||||
if (progress->get_cancel()) {
|
||||
return;
|
||||
|
@ -698,7 +698,7 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro
|
|||
ImageDataType type = img->metadata.type;
|
||||
|
||||
/* Name for debugging. */
|
||||
img->mem_name = string_printf("tex_image_%s_%03d", name_from_type(type), slot);
|
||||
img->mem_name = string_printf("tex_image_%s_%03d", name_from_type(type), (int)slot);
|
||||
|
||||
/* Free previous texture in slot. */
|
||||
if (img->mem) {
|
||||
|
@ -819,7 +819,7 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro
|
|||
img->need_load = false;
|
||||
}
|
||||
|
||||
void ImageManager::device_free_image(Device *, int slot)
|
||||
void ImageManager::device_free_image(Device *, size_t slot)
|
||||
{
|
||||
Image *img = images[slot];
|
||||
if (img == NULL) {
|
||||
|
@ -874,7 +874,10 @@ void ImageManager::device_update(Device *device, Scene *scene, Progress &progres
|
|||
need_update_ = false;
|
||||
}
|
||||
|
||||
void ImageManager::device_update_slot(Device *device, Scene *scene, int slot, Progress *progress)
|
||||
void ImageManager::device_update_slot(Device *device,
|
||||
Scene *scene,
|
||||
size_t slot,
|
||||
Progress *progress)
|
||||
{
|
||||
Image *img = images[slot];
|
||||
assert(img != NULL);
|
||||
|
|
|
@ -156,7 +156,7 @@ class ImageHandle {
|
|||
ImageManager *get_manager() const;
|
||||
|
||||
protected:
|
||||
vector<int> tile_slots;
|
||||
vector<size_t> tile_slots;
|
||||
ImageManager *manager;
|
||||
|
||||
friend class ImageManager;
|
||||
|
@ -179,7 +179,7 @@ class ImageManager {
|
|||
ImageHandle add_image(const vector<ImageLoader *> &loaders, const ImageParams ¶ms);
|
||||
|
||||
void device_update(Device *device, Scene *scene, Progress &progress);
|
||||
void device_update_slot(Device *device, Scene *scene, int slot, Progress *progress);
|
||||
void device_update_slot(Device *device, Scene *scene, size_t slot, Progress *progress);
|
||||
void device_free(Device *device);
|
||||
|
||||
void device_load_builtin(Device *device, Scene *scene, Progress &progress);
|
||||
|
@ -223,17 +223,17 @@ class ImageManager {
|
|||
vector<Image *> images;
|
||||
void *osl_texture_system;
|
||||
|
||||
int add_image_slot(ImageLoader *loader, const ImageParams ¶ms, const bool builtin);
|
||||
void add_image_user(int slot);
|
||||
void remove_image_user(int slot);
|
||||
size_t add_image_slot(ImageLoader *loader, const ImageParams ¶ms, const bool builtin);
|
||||
void add_image_user(size_t slot);
|
||||
void remove_image_user(size_t slot);
|
||||
|
||||
void load_image_metadata(Image *img);
|
||||
|
||||
template<TypeDesc::BASETYPE FileFormat, typename StorageType>
|
||||
bool file_load_image(Image *img, int texture_limit);
|
||||
|
||||
void device_load_image(Device *device, Scene *scene, int slot, Progress *progress);
|
||||
void device_free_image(Device *device, int slot);
|
||||
void device_load_image(Device *device, Scene *scene, size_t slot, Progress *progress);
|
||||
void device_free_image(Device *device, size_t slot);
|
||||
|
||||
friend class ImageHandle;
|
||||
};
|
||||
|
|
|
@ -264,9 +264,9 @@ void LightManager::device_update_distribution(Device *,
|
|||
|
||||
/* Count emissive triangles. */
|
||||
Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
|
||||
size_t mesh_num_triangles = mesh->num_triangles();
|
||||
int mesh_num_triangles = static_cast<int>(mesh->num_triangles());
|
||||
|
||||
for (size_t i = 0; i < mesh_num_triangles; i++) {
|
||||
for (int i = 0; i < mesh_num_triangles; i++) {
|
||||
int shader_index = mesh->get_shader()[i];
|
||||
Shader *shader = (shader_index < mesh->get_used_shaders().size()) ?
|
||||
static_cast<Shader *>(mesh->get_used_shaders()[shader_index]) :
|
||||
|
|
|
@ -370,9 +370,11 @@ bool LightTree::should_split(LightTreeEmitter *emitters,
|
|||
int &split_dim)
|
||||
{
|
||||
const int num_emitters = end - start;
|
||||
if (num_emitters == 1) {
|
||||
/* Do not try to split if there is only one emitter. */
|
||||
measure = (emitters + start)->measure;
|
||||
if (num_emitters < 2) {
|
||||
if (num_emitters) {
|
||||
/* Do not try to split if there is only one emitter. */
|
||||
measure = (emitters + start)->measure;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ static float3 compute_face_normal(const Mesh::Triangle &t, float3 *verts)
|
|||
/* Fill in coordinates for mesh displacement shader evaluation on device. */
|
||||
static int fill_shader_input(const Scene *scene,
|
||||
const Mesh *mesh,
|
||||
const int object_index,
|
||||
const size_t object_index,
|
||||
device_vector<KernelShaderEvalInput> &d_input)
|
||||
{
|
||||
int d_input_size = 0;
|
||||
|
|
|
@ -40,7 +40,7 @@ ccl_device_inline float half_to_float(half h_in)
|
|||
* unsigned shorts. */
|
||||
class half {
|
||||
public:
|
||||
half() : v(0) {}
|
||||
half() = default;
|
||||
half(const unsigned short &i) : v(i) {}
|
||||
operator unsigned short()
|
||||
{
|
||||
|
|
|
@ -14,62 +14,62 @@ set(INC_SYS
|
|||
)
|
||||
|
||||
set(SRC
|
||||
intern/GHOST_Buttons.cpp
|
||||
intern/GHOST_C-api.cpp
|
||||
intern/GHOST_CallbackEventConsumer.cpp
|
||||
intern/GHOST_Context.cpp
|
||||
intern/GHOST_ContextNone.cpp
|
||||
intern/GHOST_DisplayManager.cpp
|
||||
intern/GHOST_EventManager.cpp
|
||||
intern/GHOST_ISystem.cpp
|
||||
intern/GHOST_ISystemPaths.cpp
|
||||
intern/GHOST_ModifierKeys.cpp
|
||||
intern/GHOST_Path-api.cpp
|
||||
intern/GHOST_PathUtils.cpp
|
||||
intern/GHOST_Rect.cpp
|
||||
intern/GHOST_System.cpp
|
||||
intern/GHOST_TimerManager.cpp
|
||||
intern/GHOST_Window.cpp
|
||||
intern/GHOST_WindowManager.cpp
|
||||
intern/GHOST_Buttons.cc
|
||||
intern/GHOST_C-api.cc
|
||||
intern/GHOST_CallbackEventConsumer.cc
|
||||
intern/GHOST_Context.cc
|
||||
intern/GHOST_ContextNone.cc
|
||||
intern/GHOST_DisplayManager.cc
|
||||
intern/GHOST_EventManager.cc
|
||||
intern/GHOST_ISystem.cc
|
||||
intern/GHOST_ISystemPaths.cc
|
||||
intern/GHOST_ModifierKeys.cc
|
||||
intern/GHOST_Path-api.cc
|
||||
intern/GHOST_PathUtils.cc
|
||||
intern/GHOST_Rect.cc
|
||||
intern/GHOST_System.cc
|
||||
intern/GHOST_TimerManager.cc
|
||||
intern/GHOST_Window.cc
|
||||
intern/GHOST_WindowManager.cc
|
||||
|
||||
GHOST_C-api.h
|
||||
GHOST_IContext.h
|
||||
GHOST_IEvent.h
|
||||
GHOST_IEventConsumer.h
|
||||
GHOST_ISystem.h
|
||||
GHOST_ISystemPaths.h
|
||||
GHOST_ITimerTask.h
|
||||
GHOST_IWindow.h
|
||||
GHOST_Path-api.h
|
||||
GHOST_Rect.h
|
||||
GHOST_IContext.hh
|
||||
GHOST_IEvent.hh
|
||||
GHOST_IEventConsumer.hh
|
||||
GHOST_ISystem.hh
|
||||
GHOST_ISystemPaths.hh
|
||||
GHOST_ITimerTask.hh
|
||||
GHOST_IWindow.hh
|
||||
GHOST_Path-api.hh
|
||||
GHOST_Rect.hh
|
||||
GHOST_Types.h
|
||||
|
||||
intern/GHOST_Buttons.h
|
||||
intern/GHOST_CallbackEventConsumer.h
|
||||
intern/GHOST_Context.h
|
||||
intern/GHOST_ContextNone.h
|
||||
intern/GHOST_Debug.h
|
||||
intern/GHOST_DisplayManager.h
|
||||
intern/GHOST_Event.h
|
||||
intern/GHOST_EventButton.h
|
||||
intern/GHOST_EventCursor.h
|
||||
intern/GHOST_EventDragnDrop.h
|
||||
intern/GHOST_EventKey.h
|
||||
intern/GHOST_EventManager.h
|
||||
intern/GHOST_EventString.h
|
||||
intern/GHOST_EventTrackpad.h
|
||||
intern/GHOST_EventWheel.h
|
||||
intern/GHOST_ModifierKeys.h
|
||||
intern/GHOST_PathUtils.h
|
||||
intern/GHOST_System.h
|
||||
intern/GHOST_SystemPaths.h
|
||||
intern/GHOST_TimerManager.h
|
||||
intern/GHOST_TimerTask.h
|
||||
intern/GHOST_Util.h
|
||||
intern/GHOST_Window.h
|
||||
intern/GHOST_WindowManager.h
|
||||
intern/GHOST_utildefines.h
|
||||
intern/GHOST_utildefines_variadic.h
|
||||
intern/GHOST_Buttons.hh
|
||||
intern/GHOST_CallbackEventConsumer.hh
|
||||
intern/GHOST_Context.hh
|
||||
intern/GHOST_ContextNone.hh
|
||||
intern/GHOST_Debug.hh
|
||||
intern/GHOST_DisplayManager.hh
|
||||
intern/GHOST_Event.hh
|
||||
intern/GHOST_EventButton.hh
|
||||
intern/GHOST_EventCursor.hh
|
||||
intern/GHOST_EventDragnDrop.hh
|
||||
intern/GHOST_EventKey.hh
|
||||
intern/GHOST_EventManager.hh
|
||||
intern/GHOST_EventString.hh
|
||||
intern/GHOST_EventTrackpad.hh
|
||||
intern/GHOST_EventWheel.hh
|
||||
intern/GHOST_ModifierKeys.hh
|
||||
intern/GHOST_PathUtils.hh
|
||||
intern/GHOST_System.hh
|
||||
intern/GHOST_SystemPaths.hh
|
||||
intern/GHOST_TimerManager.hh
|
||||
intern/GHOST_TimerTask.hh
|
||||
intern/GHOST_Util.hh
|
||||
intern/GHOST_Window.hh
|
||||
intern/GHOST_WindowManager.hh
|
||||
intern/GHOST_utildefines.hh
|
||||
intern/GHOST_utildefines_variadic.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
@ -78,9 +78,9 @@ set(LIB
|
|||
|
||||
if(WITH_VULKAN_BACKEND)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextVK.cpp
|
||||
intern/GHOST_ContextVK.cc
|
||||
|
||||
intern/GHOST_ContextVK.h
|
||||
intern/GHOST_ContextVK.hh
|
||||
)
|
||||
|
||||
list(APPEND INC_SYS
|
||||
|
@ -98,9 +98,9 @@ endif()
|
|||
|
||||
if(WITH_GHOST_DEBUG)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_EventPrinter.cpp
|
||||
intern/GHOST_EventPrinter.cc
|
||||
|
||||
intern/GHOST_EventPrinter.h
|
||||
intern/GHOST_EventPrinter.hh
|
||||
)
|
||||
add_definitions(-DWITH_GHOST_DEBUG)
|
||||
endif()
|
||||
|
@ -109,10 +109,10 @@ if(WITH_INPUT_NDOF)
|
|||
add_definitions(-DWITH_INPUT_NDOF)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_NDOFManager.cpp
|
||||
intern/GHOST_NDOFManager.cc
|
||||
|
||||
intern/GHOST_EventNDOF.h
|
||||
intern/GHOST_NDOFManager.h
|
||||
intern/GHOST_EventNDOF.hh
|
||||
intern/GHOST_NDOFManager.hh
|
||||
)
|
||||
|
||||
list(APPEND INC_SYS
|
||||
|
@ -124,24 +124,24 @@ if(WITH_INPUT_NDOF)
|
|||
endif()
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerNULL.h
|
||||
intern/GHOST_SystemHeadless.h
|
||||
intern/GHOST_WindowNULL.h
|
||||
intern/GHOST_DisplayManagerNULL.hh
|
||||
intern/GHOST_SystemHeadless.hh
|
||||
intern/GHOST_WindowNULL.hh
|
||||
)
|
||||
|
||||
if(WITH_HEADLESS)
|
||||
add_definitions(-DWITH_HEADLESS)
|
||||
elseif(WITH_GHOST_SDL)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextSDL.cpp
|
||||
intern/GHOST_DisplayManagerSDL.cpp
|
||||
intern/GHOST_SystemSDL.cpp
|
||||
intern/GHOST_WindowSDL.cpp
|
||||
intern/GHOST_ContextSDL.cc
|
||||
intern/GHOST_DisplayManagerSDL.cc
|
||||
intern/GHOST_SystemSDL.cc
|
||||
intern/GHOST_WindowSDL.cc
|
||||
|
||||
intern/GHOST_ContextSDL.h
|
||||
intern/GHOST_DisplayManagerSDL.h
|
||||
intern/GHOST_SystemSDL.h
|
||||
intern/GHOST_WindowSDL.h
|
||||
intern/GHOST_ContextSDL.hh
|
||||
intern/GHOST_DisplayManagerSDL.hh
|
||||
intern/GHOST_SystemSDL.hh
|
||||
intern/GHOST_WindowSDL.hh
|
||||
)
|
||||
add_definitions(-DWITH_GHOST_SDL)
|
||||
|
||||
|
@ -167,23 +167,23 @@ elseif(APPLE AND NOT WITH_GHOST_X11)
|
|||
intern/GHOST_SystemCocoa.mm
|
||||
intern/GHOST_WindowCocoa.mm
|
||||
|
||||
intern/GHOST_DisplayManagerCocoa.h
|
||||
intern/GHOST_SystemCocoa.h
|
||||
intern/GHOST_WindowCocoa.h
|
||||
intern/GHOST_WindowViewCocoa.h
|
||||
intern/GHOST_DisplayManagerCocoa.hh
|
||||
intern/GHOST_SystemCocoa.hh
|
||||
intern/GHOST_WindowCocoa.hh
|
||||
intern/GHOST_WindowViewCocoa.hh
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextCGL.mm
|
||||
|
||||
intern/GHOST_ContextCGL.h
|
||||
intern/GHOST_ContextCGL.hh
|
||||
)
|
||||
|
||||
if(WITH_INPUT_NDOF)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_NDOFManagerCocoa.mm
|
||||
|
||||
intern/GHOST_NDOFManagerCocoa.h
|
||||
intern/GHOST_NDOFManagerCocoa.hh
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -199,22 +199,22 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DisplayManagerX11.cpp
|
||||
intern/GHOST_SystemX11.cpp
|
||||
intern/GHOST_TaskbarX11.cpp
|
||||
intern/GHOST_WindowX11.cpp
|
||||
intern/GHOST_DisplayManagerX11.cc
|
||||
intern/GHOST_SystemX11.cc
|
||||
intern/GHOST_TaskbarX11.cc
|
||||
intern/GHOST_WindowX11.cc
|
||||
|
||||
intern/GHOST_DisplayManagerX11.h
|
||||
intern/GHOST_IconX11.h
|
||||
intern/GHOST_SystemX11.h
|
||||
intern/GHOST_TaskbarX11.h
|
||||
intern/GHOST_WindowX11.h
|
||||
intern/GHOST_DisplayManagerX11.hh
|
||||
intern/GHOST_IconX11.hh
|
||||
intern/GHOST_SystemX11.hh
|
||||
intern/GHOST_TaskbarX11.hh
|
||||
intern/GHOST_WindowX11.hh
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextGLX.cpp
|
||||
intern/GHOST_ContextGLX.cc
|
||||
|
||||
intern/GHOST_ContextGLX.h
|
||||
intern/GHOST_ContextGLX.hh
|
||||
)
|
||||
|
||||
if(WITH_GHOST_XDND)
|
||||
|
@ -229,9 +229,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_DropTargetX11.cpp
|
||||
intern/GHOST_DropTargetX11.cc
|
||||
|
||||
intern/GHOST_DropTargetX11.h
|
||||
intern/GHOST_DropTargetX11.hh
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -336,13 +336,13 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
endif()
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_SystemWayland.cpp
|
||||
intern/GHOST_WindowWayland.cpp
|
||||
intern/GHOST_SystemWayland.cc
|
||||
intern/GHOST_WindowWayland.cc
|
||||
|
||||
intern/GHOST_SystemWayland.h
|
||||
intern/GHOST_WaylandCursorSettings.h
|
||||
intern/GHOST_WaylandUtils.h
|
||||
intern/GHOST_WindowWayland.h
|
||||
intern/GHOST_SystemWayland.hh
|
||||
intern/GHOST_WaylandCursorSettings.hh
|
||||
intern/GHOST_WaylandUtils.hh
|
||||
intern/GHOST_WindowWayland.hh
|
||||
)
|
||||
|
||||
set(INC_DST ${CMAKE_CURRENT_BINARY_DIR}/libwayland)
|
||||
|
@ -441,9 +441,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
|||
|
||||
if(WITH_INPUT_NDOF)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_NDOFManagerUnix.cpp
|
||||
intern/GHOST_NDOFManagerUnix.cc
|
||||
|
||||
intern/GHOST_NDOFManagerUnix.h
|
||||
intern/GHOST_NDOFManagerUnix.hh
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -463,67 +463,67 @@ elseif(WIN32)
|
|||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextD3D.cpp
|
||||
intern/GHOST_DisplayManagerWin32.cpp
|
||||
intern/GHOST_DropTargetWin32.cpp
|
||||
intern/GHOST_SystemWin32.cpp
|
||||
intern/GHOST_TrackpadWin32.cpp
|
||||
intern/GHOST_WindowWin32.cpp
|
||||
intern/GHOST_Wintab.cpp
|
||||
intern/GHOST_ContextD3D.cc
|
||||
intern/GHOST_DisplayManagerWin32.cc
|
||||
intern/GHOST_DropTargetWin32.cc
|
||||
intern/GHOST_SystemWin32.cc
|
||||
intern/GHOST_TrackpadWin32.cc
|
||||
intern/GHOST_WindowWin32.cc
|
||||
intern/GHOST_Wintab.cc
|
||||
|
||||
intern/GHOST_ContextD3D.h
|
||||
intern/GHOST_DisplayManagerWin32.h
|
||||
intern/GHOST_DropTargetWin32.h
|
||||
intern/GHOST_SystemWin32.h
|
||||
intern/GHOST_TaskbarWin32.h
|
||||
intern/GHOST_TrackpadWin32.h
|
||||
intern/GHOST_WindowWin32.h
|
||||
intern/GHOST_Wintab.h
|
||||
intern/GHOST_ContextD3D.hh
|
||||
intern/GHOST_DisplayManagerWin32.hh
|
||||
intern/GHOST_DropTargetWin32.hh
|
||||
intern/GHOST_SystemWin32.hh
|
||||
intern/GHOST_TaskbarWin32.hh
|
||||
intern/GHOST_TrackpadWin32.hh
|
||||
intern/GHOST_WindowWin32.hh
|
||||
intern/GHOST_Wintab.hh
|
||||
)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextWGL.cpp
|
||||
intern/GHOST_ContextWGL.cc
|
||||
|
||||
intern/GHOST_ContextWGL.h
|
||||
intern/GHOST_ContextWGL.hh
|
||||
)
|
||||
|
||||
if(WITH_INPUT_IME)
|
||||
add_definitions(-DWITH_INPUT_IME)
|
||||
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ImeWin32.cpp
|
||||
intern/GHOST_ImeWin32.cc
|
||||
|
||||
intern/GHOST_ImeWin32.h
|
||||
intern/GHOST_ImeWin32.hh
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WITH_INPUT_NDOF)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_NDOFManagerWin32.cpp
|
||||
intern/GHOST_NDOFManagerWin32.cc
|
||||
|
||||
intern/GHOST_NDOFManagerWin32.h
|
||||
intern/GHOST_NDOFManagerWin32.hh
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_ContextEGL.cpp
|
||||
intern/GHOST_ContextEGL.cc
|
||||
|
||||
intern/GHOST_ContextEGL.h
|
||||
intern/GHOST_ContextEGL.hh
|
||||
)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_SystemPathsCocoa.h
|
||||
intern/GHOST_SystemPathsCocoa.hh
|
||||
intern/GHOST_SystemPathsCocoa.mm
|
||||
)
|
||||
|
||||
elseif(UNIX)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_SystemPathsUnix.cpp
|
||||
intern/GHOST_SystemPathsUnix.h
|
||||
intern/GHOST_SystemPathsUnix.cc
|
||||
intern/GHOST_SystemPathsUnix.hh
|
||||
)
|
||||
|
||||
if(NOT WITH_INSTALL_PORTABLE)
|
||||
|
@ -532,8 +532,8 @@ elseif(UNIX)
|
|||
|
||||
elseif(WIN32)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_SystemPathsWin32.cpp
|
||||
intern/GHOST_SystemPathsWin32.h
|
||||
intern/GHOST_SystemPathsWin32.cc
|
||||
intern/GHOST_SystemPathsWin32.hh
|
||||
)
|
||||
|
||||
list(APPEND INC
|
||||
|
@ -544,25 +544,25 @@ endif()
|
|||
|
||||
if(WITH_XR_OPENXR)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_Xr.cpp
|
||||
intern/GHOST_XrAction.cpp
|
||||
intern/GHOST_XrContext.cpp
|
||||
intern/GHOST_XrControllerModel.cpp
|
||||
intern/GHOST_XrEvent.cpp
|
||||
intern/GHOST_XrGraphicsBinding.cpp
|
||||
intern/GHOST_XrSession.cpp
|
||||
intern/GHOST_XrSwapchain.cpp
|
||||
intern/GHOST_Xr.cc
|
||||
intern/GHOST_XrAction.cc
|
||||
intern/GHOST_XrContext.cc
|
||||
intern/GHOST_XrControllerModel.cc
|
||||
intern/GHOST_XrEvent.cc
|
||||
intern/GHOST_XrGraphicsBinding.cc
|
||||
intern/GHOST_XrSession.cc
|
||||
intern/GHOST_XrSwapchain.cc
|
||||
|
||||
GHOST_IXrContext.h
|
||||
intern/GHOST_IXrGraphicsBinding.h
|
||||
intern/GHOST_XrAction.h
|
||||
intern/GHOST_XrContext.h
|
||||
intern/GHOST_XrControllerModel.h
|
||||
intern/GHOST_XrException.h
|
||||
intern/GHOST_XrSession.h
|
||||
intern/GHOST_XrSwapchain.h
|
||||
intern/GHOST_Xr_intern.h
|
||||
intern/GHOST_Xr_openxr_includes.h
|
||||
GHOST_IXrContext.hh
|
||||
intern/GHOST_IXrGraphicsBinding.hh
|
||||
intern/GHOST_XrAction.hh
|
||||
intern/GHOST_XrContext.hh
|
||||
intern/GHOST_XrControllerModel.hh
|
||||
intern/GHOST_XrException.hh
|
||||
intern/GHOST_XrSession.hh
|
||||
intern/GHOST_XrSwapchain.hh
|
||||
intern/GHOST_Xr_intern.hh
|
||||
intern/GHOST_Xr_openxr_includes.hh
|
||||
|
||||
# Header only library.
|
||||
../../extern/tinygltf/tiny_gltf.h
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_IEvent.h"
|
||||
#include "GHOST_IEvent.hh"
|
||||
|
||||
/**
|
||||
* Interface class for objects interested in receiving events.
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "GHOST_IContext.h"
|
||||
#include "GHOST_ITimerTask.h"
|
||||
#include "GHOST_IWindow.h"
|
||||
#include "GHOST_IContext.hh"
|
||||
#include "GHOST_ITimerTask.hh"
|
||||
#include "GHOST_IWindow.hh"
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
class GHOST_IEventConsumer;
|
||||
|
@ -77,12 +77,12 @@ class GHOST_IEventConsumer;
|
|||
*
|
||||
* \subsection cplusplus_api The C++ API consists of the following files:
|
||||
*
|
||||
* - GHOST_IEvent.h
|
||||
* - GHOST_IEventConsumer.h
|
||||
* - GHOST_ISystem.h
|
||||
* - GHOST_ITimerTask.h
|
||||
* - GHOST_IWindow.h
|
||||
* - GHOST_Rect.h
|
||||
* - GHOST_IEvent.hh
|
||||
* - GHOST_IEventConsumer.hh
|
||||
* - GHOST_ISystem.hh
|
||||
* - GHOST_ITimerTask.hh
|
||||
* - GHOST_IWindow.hh
|
||||
* - GHOST_Rect.hh
|
||||
* - GHOST_Types.h
|
||||
*
|
||||
* For an example of using the C++-API, have a look at the GHOST_C-Test.cpp
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_Rect.h"
|
||||
#include "GHOST_Rect.hh"
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
#include <stdlib.h>
|
|
@ -5,7 +5,7 @@
|
|||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#include "GHOST_Buttons.h"
|
||||
#include "GHOST_Buttons.hh"
|
||||
|
||||
GHOST_Buttons::GHOST_Buttons()
|
||||
{
|
|
@ -11,16 +11,16 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_IEvent.h"
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
#include "GHOST_ISystem.h"
|
||||
#include "intern/GHOST_Debug.h"
|
||||
#include "GHOST_IEvent.hh"
|
||||
#include "GHOST_IEventConsumer.hh"
|
||||
#include "GHOST_ISystem.hh"
|
||||
#include "intern/GHOST_Debug.hh"
|
||||
#ifdef WITH_XR_OPENXR
|
||||
# include "GHOST_IXrContext.h"
|
||||
# include "intern/GHOST_XrSession.h"
|
||||
# include "GHOST_IXrContext.hh"
|
||||
# include "intern/GHOST_XrSession.hh"
|
||||
#endif
|
||||
#include "intern/GHOST_CallbackEventConsumer.h"
|
||||
#include "intern/GHOST_XrException.h"
|
||||
#include "intern/GHOST_CallbackEventConsumer.hh"
|
||||
#include "intern/GHOST_XrException.hh"
|
||||
|
||||
GHOST_SystemHandle GHOST_CreateSystem(void)
|
||||
{
|
|
@ -9,9 +9,9 @@
|
|||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
*/
|
||||
|
||||
#include "GHOST_CallbackEventConsumer.h"
|
||||
#include "GHOST_CallbackEventConsumer.hh"
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_Debug.hh"
|
||||
|
||||
GHOST_CallbackEventConsumer::GHOST_CallbackEventConsumer(GHOST_EventCallbackProcPtr eventCallback,
|
||||
GHOST_TUserDataPtr userData)
|
|
@ -9,7 +9,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "GHOST_C-api.h"
|
||||
#include "GHOST_IEventConsumer.h"
|
||||
#include "GHOST_IEventConsumer.hh"
|
||||
|
||||
/**
|
||||
* Event consumer that will forward events to a call-back routine.
|
|
@ -7,7 +7,7 @@
|
|||
* Definition of GHOST_Context class.
|
||||
*/
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <epoxy/wgl.h>
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_IContext.h"
|
||||
#include "GHOST_IContext.hh"
|
||||
#include "GHOST_Types.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Metal/Metal.h>
|
|
@ -13,7 +13,7 @@
|
|||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
#include "GHOST_ContextCGL.h"
|
||||
#include "GHOST_ContextCGL.hh"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Metal/Metal.h>
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
#include <epoxy/wgl.h>
|
||||
|
||||
#include "GHOST_ContextD3D.h"
|
||||
#include "GHOST_ContextWGL.h" /* For shared drawing */
|
||||
#include "GHOST_ContextD3D.hh"
|
||||
#include "GHOST_ContextWGL.hh" /* For shared drawing */
|
||||
|
||||
HMODULE GHOST_ContextD3D::s_d3d_lib = NULL;
|
||||
PFN_D3D11_CREATE_DEVICE GHOST_ContextD3D::s_D3D11CreateDeviceFn = NULL;
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include <D3D11.h>
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
class GHOST_ContextD3D : public GHOST_Context {
|
||||
/* XR code needs low level graphics data to send to OpenXR. */
|
|
@ -7,7 +7,7 @@
|
|||
* Definition of GHOST_ContextEGL class.
|
||||
*/
|
||||
|
||||
#include "GHOST_ContextEGL.h"
|
||||
#include "GHOST_ContextEGL.hh"
|
||||
|
||||
#include <set>
|
||||
#include <sstream>
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_System.h"
|
||||
#include "GHOST_Context.hh"
|
||||
#include "GHOST_System.hh"
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
#include <epoxy/gl.h>
|
|
@ -7,8 +7,8 @@
|
|||
* Definition of GHOST_ContextGLX class.
|
||||
*/
|
||||
|
||||
#include "GHOST_ContextGLX.h"
|
||||
#include "GHOST_SystemX11.h"
|
||||
#include "GHOST_ContextGLX.hh"
|
||||
#include "GHOST_SystemX11.hh"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
#include <epoxy/glx.h>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
* Definition of GHOST_ContextNone class.
|
||||
*/
|
||||
|
||||
#include "GHOST_ContextNone.h"
|
||||
#include "GHOST_ContextNone.hh"
|
||||
|
||||
GHOST_TSuccess GHOST_ContextNone::swapBuffers()
|
||||
{
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
class GHOST_ContextNone : public GHOST_Context {
|
||||
public:
|
|
@ -7,7 +7,7 @@
|
|||
* Definition of GHOST_ContextSDL class.
|
||||
*/
|
||||
|
||||
#include "GHOST_ContextSDL.h"
|
||||
#include "GHOST_ContextSDL.hh"
|
||||
|
||||
#include <vector>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
extern "C" {
|
||||
#include "SDL.h"
|
|
@ -4,7 +4,7 @@
|
|||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#include "GHOST_ContextVK.h"
|
||||
#include "GHOST_ContextVK.hh"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <vulkan/vulkan_win32.h>
|
|
@ -6,16 +6,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "GHOST_SystemWin32.h"
|
||||
# include "GHOST_SystemWin32.hh"
|
||||
#elif defined(__APPLE__)
|
||||
# include "GHOST_SystemCocoa.h"
|
||||
# include "GHOST_SystemCocoa.hh"
|
||||
#else
|
||||
# include "GHOST_SystemX11.h"
|
||||
# include "GHOST_SystemX11.hh"
|
||||
# ifdef WITH_GHOST_WAYLAND
|
||||
# include "GHOST_SystemWayland.h"
|
||||
# include "GHOST_SystemWayland.hh"
|
||||
# else
|
||||
# define wl_surface void
|
||||
# define wl_display void
|
|
@ -7,7 +7,7 @@
|
|||
* Definition of GHOST_ContextWGL class.
|
||||
*/
|
||||
|
||||
#include "GHOST_ContextWGL.h"
|
||||
#include "GHOST_ContextWGL.hh"
|
||||
|
||||
#include <tchar.h>
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
//#define WIN32_COMPOSITING
|
||||
|
||||
#include "GHOST_Context.h"
|
||||
#include "GHOST_Context.hh"
|
||||
|
||||
#include <epoxy/wgl.h>
|
||||
|
|
@ -9,8 +9,8 @@
|
|||
* Copyright (C) 2001 NaN Technologies B.V.
|
||||
*/
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
#include "GHOST_Debug.h"
|
||||
#include "GHOST_DisplayManager.hh"
|
||||
#include "GHOST_Debug.hh"
|
||||
|
||||
GHOST_DisplayManager::GHOST_DisplayManager() : m_settingsInitialized(false) {}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue