Compare commits
336 Commits
tmp-eevee-
...
tmp-widget
Author | SHA1 | Date | |
---|---|---|---|
e76ff4df41 | |||
528f0b95c4 | |||
41bb0548b0 | |||
9b9f84b317 | |||
5a842b3412 | |||
c15bb3b55f | |||
ffcb87813b | |||
dc429d5910 | |||
31f3e9082a | |||
f274b8c102 | |||
0700521833 | |||
5db2d9c82b | |||
f13b687551 | |||
0d0df683d9 | |||
6b8555e01c | |||
8e4c74292a | |||
f43bb98646 | |||
22462fed00 | |||
525fc36a80 | |||
2ddd9813ef | |||
157b9e78a4 | |||
93f60a4da5 | |||
f5cd06ed45 | |||
1f34a34fa5 | |||
6f8d99322c | |||
041e440649 | |||
b4613e0bca | |||
08c1f5bf33 | |||
86fa8dc7f7 | |||
ece8ecb4dd | |||
![]() |
e8dd8c2829 | ||
f27e122d95 | |||
e8209c36e6 | |||
45f17e10ec | |||
a958725f81 | |||
3bc15c097c | |||
43d33b3626 | |||
98689f51c0 | |||
cbd4b8ebb0 | |||
c75a665c44 | |||
06860ba29b | |||
a76e804309 | |||
1633a65d41 | |||
![]() |
0236863c6d | ||
920b698746 | |||
8ddcc7fd51 | |||
69e331201e | |||
![]() |
59aed2a255 | ||
f990b42504 | |||
f5c682045d | |||
4066c921fb | |||
c4edc6f3f7 | |||
a1a333a1e9 | |||
fbbc0229b8 | |||
b87d81be96 | |||
fe739f8c26 | |||
ce6fd6b6a2 | |||
![]() |
42f8d52401 | ||
3aacd8a4ab | |||
1b994a37f4 | |||
8f21f867e7 | |||
70c483e7db | |||
3cb6efd3ab | |||
1f6ef73f98 | |||
c732edbaa4 | |||
ce74df6248 | |||
7e4654e4ce | |||
df14b11526 | |||
a39ca327bc | |||
de7d32bb7d | |||
2fe615ab9f | |||
8a8c61190b | |||
0c9e73845c | |||
03d8783db0 | |||
376b69cbff | |||
2efd00d4d2 | |||
d15efbdc56 | |||
850fbe8547 | |||
c13bf40ab1 | |||
0ff663b6fc | |||
8d648e0972 | |||
fcfb87def9 | |||
f66bfb5a86 | |||
bbef6fe336 | |||
8ecfa6a828 | |||
b4a6418e2b | |||
522e6c0c06 | |||
8a0840b0ee | |||
af3a55bb1b | |||
71fa460145 | |||
6d7dc2265f | |||
8bff3ec76b | |||
600fd1c6f0 | |||
29afadcb15 | |||
b9aa2acecd | |||
e2b87aabb6 | |||
1c79484d53 | |||
3a284a37fd | |||
ee44283393 | |||
2059b30ee2 | |||
4d613018ee | |||
e2d961809b | |||
140935ee7e | |||
e4e31e4f14 | |||
93b5682444 | |||
e15ffc0c54 | |||
796412dca0 | |||
8fe448b44d | |||
ccf43fe605 | |||
aa0e98d707 | |||
b44101950d | |||
c1545c9a9d | |||
717577d5fc | |||
e1050fb395 | |||
9897ef6a20 | |||
22c30219e7 | |||
d33c27d68b | |||
3a5a158362 | |||
707a4c355f | |||
eb57377f12 | |||
7d3bf5166d | |||
578b0c00ca | |||
3360db83c4 | |||
db6e267bfc | |||
ec86db82b0 | |||
5fe7605f3d | |||
f69ecce14b | |||
a296dff2c8 | |||
31137004ae | |||
bfdfa35e6e | |||
aa02a05bc7 | |||
dfe8195dfe | |||
8f050b6825 | |||
499c0229f7 | |||
4f622c9a08 | |||
e610964e89 | |||
183ba284f2 | |||
120e9924c1 | |||
33fc42bd65 | |||
5ca8875f69 | |||
3bced3b306 | |||
5267ce8e03 | |||
59cfb20fa1 | |||
8d63d7337c | |||
20c30534aa | |||
42d77fbea1 | |||
8e0a57f9bd | |||
c554f4e14f | |||
13125e0948 | |||
a5a069c272 | |||
0a19b8a5b4 | |||
a3bdbb5e5b | |||
d6cc16831a | |||
5201bc9dd4 | |||
e73d7d27dc | |||
7bb3d9787e | |||
61280e5af3 | |||
fa270a37e8 | |||
a4cbacacbf | |||
08b4faef01 | |||
a6c0874355 | |||
059f79bdd7 | |||
cfb7664d5b | |||
dd62d95687 | |||
7fcf2e7d4a | |||
813ff8913b | |||
338abd6f68 | |||
0c20fce2f2 | |||
![]() |
03fa66d274 | ||
46c35dc283 | |||
a95afed6de | |||
9ccc73ade8 | |||
![]() |
9ac4e4a1c7 | ||
cc485191e4 | |||
a6646fb0d0 | |||
8c4965f86d | |||
14278cd932 | |||
eb1cb7cb81 | |||
30cbbccc60 | |||
22998abe92 | |||
675ba2073d | |||
325307d82b | |||
4fa1fc29bd | |||
e5c5e25c68 | |||
82bda82ec4 | |||
25dea3e65e | |||
10528a5cd4 | |||
24e5c64ea2 | |||
cddfa7a449 | |||
b96ccb5126 | |||
f89b89fa7f | |||
291136eece | |||
888427cabb | |||
fc06c248ed | |||
ac8b36535e | |||
5fa58fb8a2 | |||
1151bcd53d | |||
f557198540 | |||
15bf81268c | |||
1afa97d547 | |||
7bd07c9f5a | |||
ff7a30d928 | |||
79a48c5676 | |||
7c9c8cee7b | |||
393050e8e5 | |||
497cd3d7dd | |||
c4ee94328f | |||
0bdb827bdf | |||
e0ae229acb | |||
afbe71342b | |||
06c57d3e7a | |||
8f10f9d5dc | |||
ae97a7ac10 | |||
38a8d3aff1 | |||
46a4a53824 | |||
35f9c3b9a4 | |||
20b94257dc | |||
31fc01eecb | |||
9bc7ea5496 | |||
fa116a9bbe | |||
2ad5131f77 | |||
22f68f85a4 | |||
54665233eb | |||
151fb62190 | |||
0d57ab611c | |||
6eb00fb02e | |||
0bd7e202fb | |||
cb8d8335b2 | |||
19413c4a82 | |||
48a5b1664a | |||
27cac4a102 | |||
121b2c0424 | |||
dcf67fdf7f | |||
27b23148fa | |||
6ede93bab3 | |||
18dd289e1a | |||
80b340b034 | |||
b487ef6116 | |||
b75ce05c3b | |||
b1492b76ba | |||
9796cb1661 | |||
f3edff2d7d | |||
005d04e145 | |||
a432cb2ad9 | |||
008e964940 | |||
470ed9f074 | |||
04d15f1625 | |||
52d8b3a014 | |||
a4b2734fe2 | |||
68ba154869 | |||
fd8d2ceafe | |||
815ffaa6c1 | |||
98e18c41b6 | |||
2a3797b109 | |||
ff144edd8c | |||
218579fa53 | |||
cfea716128 | |||
41825c7e0d | |||
9af72792a3 | |||
5c5a638b57 | |||
dde7a762c3 | |||
fe257cc384 | |||
a975cb9207 | |||
0abe5936b7 | |||
15dd6cb668 | |||
eaf7d36d66 | |||
d9773edaa3 | |||
3ff8ca60e9 | |||
e5ace51295 | |||
e1c2eba4de | |||
abcb23f5a3 | |||
a8fc3c88ef | |||
7ff933089a | |||
c44d6fb987 | |||
0055aa994d | |||
a952f8dab0 | |||
001d70eb2b | |||
ecec6547c7 | |||
9632a06201 | |||
b14243be77 | |||
0f2c7f3864 | |||
0541906162 | |||
363f18c8b5 | |||
1cad0a627e | |||
d6e0b55b1c | |||
a269761ec1 | |||
b67f649077 | |||
266caa1820 | |||
1aace88d0c | |||
291f9462fc | |||
998e26704b | |||
fe0036c586 | |||
0538d00cc2 | |||
2b36cf3118 | |||
86580c437b | |||
03659c2cf9 | |||
a5d394fad2 | |||
0a32f6c868 | |||
3a14c011f9 | |||
04517ee936 | |||
0ae64a9945 | |||
5f95912afc | |||
7049d2dc58 | |||
547f50b5e0 | |||
6398892121 | |||
f1cb11f0fa | |||
19d822c677 | |||
e60560bda0 | |||
559a8886d6 | |||
20c25bffda | |||
656692913b | |||
3c0fd51cf4 | |||
6a850f3cc8 | |||
c361f911f9 | |||
191c562f98 | |||
4ce1829289 | |||
c880e54a95 | |||
8d918fe0f2 | |||
f716bb3b71 | |||
516e1b4031 | |||
2efe77ca51 | |||
![]() |
3ced9c1c72 | ||
6716baa1f7 | |||
4ac748c099 | |||
5f31e5031c | |||
cc3d3a453e | |||
![]() |
33ce0cb5a1 | ||
461fee5328 | |||
5940485369 | |||
16d8a683be | |||
ea84c12a2b | |||
72492eb2a2 | |||
dc4983dfdd | |||
78e3b7c28d | |||
fa23e313f1 | |||
e585257063 |
@@ -281,7 +281,7 @@ option(WITH_ALEMBIC "Enable Alembic Support" ON)
|
||||
option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF)
|
||||
|
||||
# Universal Scene Description support
|
||||
option(WITH_USD "Enable Universal Scene Description (USD) Support" OFF)
|
||||
option(WITH_USD "Enable Universal Scene Description (USD) Support" ON)
|
||||
|
||||
# 3D format support
|
||||
# Disable opencollada when we don't have precompiled libs
|
||||
@@ -628,12 +628,6 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL)
|
||||
message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF")
|
||||
endif()
|
||||
|
||||
|
||||
# may as well build python module without a UI
|
||||
if(WITH_PYTHON_MODULE)
|
||||
set(WITH_HEADLESS ON)
|
||||
endif()
|
||||
|
||||
if(NOT WITH_PYTHON)
|
||||
set(WITH_CYCLES OFF)
|
||||
set(WITH_DRACO OFF)
|
||||
|
@@ -130,7 +130,6 @@ if(NOT WIN32 OR ENABLE_MINGW64)
|
||||
include(cmake/vpx.cmake)
|
||||
include(cmake/x264.cmake)
|
||||
include(cmake/xvidcore.cmake)
|
||||
include(cmake/faad.cmake)
|
||||
include(cmake/ffmpeg.cmake)
|
||||
include(cmake/fftw.cmake)
|
||||
include(cmake/sndfile.cmake)
|
||||
|
@@ -1,40 +0,0 @@
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
set(FAAD_EXTRA_ARGS)
|
||||
|
||||
if(WIN32)
|
||||
set(FAAD_EXTRA_CONFIGURE "utils\\win32\\ac2ver.exe" "faad2" "configure.ac" > libfaad\\win32_ver.h)
|
||||
else()
|
||||
set(FAAD_EXTRA_CONFIGURE echo .)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_faad
|
||||
URL ${FAAD_URI}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${FAAD_HASH}
|
||||
PREFIX ${BUILD_DIR}/faad
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/faad/src/external_faad/ && ${FAAD_EXTRA_CONFIGURE} && ${CONFIGURE_COMMAND} --disable-shared --enable-static --prefix=${LIBDIR}/faad
|
||||
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/faad/src/external_faad/ && make -j${MAKE_THREADS}
|
||||
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/faad/src/external_faad/ && make install
|
||||
INSTALL_DIR ${LIBDIR}/faad
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
set_target_properties(external_faad PROPERTIES FOLDER Mingw)
|
||||
endif()
|
@@ -127,7 +127,6 @@ endif()
|
||||
add_dependencies(
|
||||
external_ffmpeg
|
||||
external_zlib
|
||||
external_faad
|
||||
external_openjpeg
|
||||
external_xvidcore
|
||||
external_x264
|
||||
|
@@ -19,8 +19,12 @@
|
||||
set(FFTW_EXTRA_ARGS)
|
||||
|
||||
if(WIN32)
|
||||
set(FFTW3_ENV set CFLAGS=-fno-stack-check -fno-stack-protector -mno-stack-arg-probe -fno-lto &&)
|
||||
set(FFTW3_PATCH_COMMAND ${PATCH_CMD} --verbose -p 0 -N -d ${BUILD_DIR}/fftw3/src/external_fftw3 < ${PATCH_DIR}/fftw3.diff)
|
||||
set(FFTW_EXTRA_ARGS --disable-static --enable-shared)
|
||||
set(FFTW_INSTALL install-strip)
|
||||
else()
|
||||
set(FFTW_EXTRA_ARGS --enable-static)
|
||||
set(FFTW_INSTALL install)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(external_fftw3
|
||||
@@ -28,10 +32,10 @@ ExternalProject_Add(external_fftw3
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${FFTW_HASH}
|
||||
PREFIX ${BUILD_DIR}/fftw3
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && ${FFTW3_ENV} cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && ${CONFIGURE_COMMAND} --enable-static --prefix=${mingw_LIBDIR}/fftw3
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && ${CONFIGURE_COMMAND} ${FFTW_EXTRA_ARGS} --prefix=${mingw_LIBDIR}/fftw3
|
||||
PATCH_COMMAND ${FFTW3_PATCH_COMMAND}
|
||||
BUILD_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && make -j${MAKE_THREADS}
|
||||
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && make install
|
||||
INSTALL_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/fftw3/src/external_fftw3/ && make ${FFTW_INSTALL}
|
||||
INSTALL_DIR ${LIBDIR}/fftw3
|
||||
)
|
||||
|
||||
@@ -39,7 +43,8 @@ if(MSVC)
|
||||
set_target_properties(external_fftw3 PROPERTIES FOLDER Mingw)
|
||||
if(BUILD_MODE STREQUAL Release)
|
||||
ExternalProject_Add_Step(external_fftw3 after_install
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/lib/libfftw3.a ${HARVEST_TARGET}/fftw3/lib/libfftw.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/lib/libfftw3.dll.a ${HARVEST_TARGET}/fftw3/lib/libfftw.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/bin/libfftw3-3.dll ${HARVEST_TARGET}/fftw3/lib/libfftw3-3.dll
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/fftw3/include/fftw3.h ${HARVEST_TARGET}/fftw3/include/fftw3.h
|
||||
DEPENDEES install
|
||||
)
|
||||
|
@@ -44,10 +44,6 @@ if(BUILD_MODE STREQUAL Release)
|
||||
# glew-> opengl
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/glew/lib/libglew32.lib ${HARVEST_TARGET}/opengl/lib/glew.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/glew/include/ ${HARVEST_TARGET}/opengl/include/ &&
|
||||
# sndfile
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/lib/libsndfile.dll.a ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.lib &&
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/bin/libsndfile-1.dll ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.dll &&
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/include/sndfile.h ${HARVEST_TARGET}/sndfile/include/sndfile.h &&
|
||||
# tiff
|
||||
${CMAKE_COMMAND} -E copy ${LIBDIR}/tiff/lib/tiff.lib ${HARVEST_TARGET}/tiff/lib/libtiff.lib &&
|
||||
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/tiff/include/ ${HARVEST_TARGET}/tiff/include/ &&
|
||||
|
@@ -52,7 +52,6 @@ if(BUILD_MODE STREQUAL Release)
|
||||
PREFIX ${BUILD_DIR}/openal
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openal ${DEFAULT_CMAKE_FLAGS} ${OPENAL_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/openal
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openal/src/external_openal < ${PATCH_DIR}/openal.diff
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
@@ -67,7 +67,7 @@ endif()
|
||||
ExternalProject_Add(external_opensubdiv
|
||||
URL ${OPENSUBDIV_URI}
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH MD5=${OPENSUBDIV_Hash}
|
||||
URL_HASH MD5=${OPENSUBDIV_HASH}
|
||||
PREFIX ${BUILD_DIR}/opensubdiv
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/opensubdiv -Wno-dev ${DEFAULT_CMAKE_FLAGS} ${OPENSUBDIV_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/opensubdiv
|
||||
|
@@ -60,3 +60,14 @@ if(UNIX)
|
||||
external_flac
|
||||
)
|
||||
endif()
|
||||
|
||||
if(BUILD_MODE STREQUAL Release AND WIN32)
|
||||
ExternalProject_Add_Step(external_sndfile after_install
|
||||
COMMAND lib /def:${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.def /machine:x64 /out:${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/bin/libsndfile-1.dll ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.dll
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILD_DIR}/sndfile/src/external_sndfile/src/libsndfile-1.lib ${HARVEST_TARGET}/sndfile/lib/libsndfile-1.lib
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/sndfile/include/sndfile.h ${HARVEST_TARGET}/sndfile/include/sndfile.h
|
||||
|
||||
DEPENDEES install
|
||||
)
|
||||
endif()
|
||||
|
@@ -20,9 +20,9 @@ set(ZLIB_VERSION 1.2.11)
|
||||
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
|
||||
set(ZLIB_HASH 1c9f62f0778697a09d36121ead88e08e)
|
||||
|
||||
set(OPENAL_VERSION 1.18.2)
|
||||
set(OPENAL_VERSION 1.20.1)
|
||||
set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
|
||||
set(OPENAL_HASH d4eeb0889812e2fdeaa1843523d76190)
|
||||
set(OPENAL_HASH 556695068ce8375b89986083d810fd35)
|
||||
|
||||
set(PNG_VERSION 1.6.35)
|
||||
set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.xz)
|
||||
@@ -66,9 +66,9 @@ else()
|
||||
set(OPENEXR_VERSION_POSTFIX)
|
||||
endif()
|
||||
|
||||
set(FREETYPE_VERSION 2.10.1)
|
||||
set(FREETYPE_VERSION 2.10.2)
|
||||
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
|
||||
set(FREETYPE_HASH c50a3c9e5e62bdc938a6e1598a782947)
|
||||
set(FREETYPE_HASH b1cb620e4c875cd4d1bfa04945400945)
|
||||
|
||||
set(GLEW_VERSION 1.13.0)
|
||||
set(GLEW_URI http://prdownloads.sourceforge.net/glew/glew/${GLEW_VERSION}/glew-${GLEW_VERSION}.tgz)
|
||||
@@ -101,13 +101,13 @@ set(CUEW_GIT_UID 1744972026de9cf27c8a7dc39cf39cd83d5f922f)
|
||||
set(CUEW_URI https://github.com/CudaWrangler/cuew/archive/${CUEW_GIT_UID}.zip)
|
||||
set(CUEW_HASH 86760d62978ebfd96cd93f5aa1abaf4a)
|
||||
|
||||
set(OPENSUBDIV_VERSION v3_4_0_RC2)
|
||||
set(OPENSUBDIV_Hash f6a10ba9efaa82fde86fe65aad346319)
|
||||
set(OPENSUBDIV_VERSION v3_4_3)
|
||||
set(OPENSUBDIV_URI https://github.com/PixarAnimationStudios/OpenSubdiv/archive/${OPENSUBDIV_VERSION}.tar.gz)
|
||||
set(OPENSUBDIV_HASH 7bbfa275d021fb829e521df749160edb)
|
||||
|
||||
set(SDL_VERSION 2.0.8)
|
||||
set(SDL_VERSION 2.0.12)
|
||||
set(SDL_URI https://www.libsdl.org/release/SDL2-${SDL_VERSION}.tar.gz)
|
||||
set(SDL_HASH 3800d705cef742c6a634f202c37f263f)
|
||||
set(SDL_HASH 783b6f2df8ff02b19bb5ce492b99c8ff)
|
||||
|
||||
set(OPENCOLLADA_VERSION v1.6.68)
|
||||
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
|
||||
@@ -168,9 +168,9 @@ set(LAME_VERSION 3.100)
|
||||
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz)
|
||||
set(LAME_HASH 83e260acbe4389b54fe08e0bdbf7cddb)
|
||||
|
||||
set(OGG_VERSION 1.3.3)
|
||||
set(OGG_VERSION 1.3.4)
|
||||
set(OGG_URI http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz)
|
||||
set(OGG_HASH c2e8a485110b97550f453226ec644ebac6cb29d1caef2902c007edab4308d985)
|
||||
set(OGG_HASH fe5670640bd49e828d64d2879c31cb4dde9758681bb664f9bdbf159a01b0c76e)
|
||||
|
||||
set(VORBIS_VERSION 1.3.6)
|
||||
set(VORBIS_URI http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERSION}.tar.gz)
|
||||
@@ -180,24 +180,24 @@ set(THEORA_VERSION 1.1.1)
|
||||
set(THEORA_URI http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.bz2)
|
||||
set(THEORA_HASH b6ae1ee2fa3d42ac489287d3ec34c5885730b1296f0801ae577a35193d3affbc)
|
||||
|
||||
set(FLAC_VERSION 1.3.2)
|
||||
set(FLAC_VERSION 1.3.3)
|
||||
set(FLAC_URI http://downloads.xiph.org/releases/flac/flac-${FLAC_VERSION}.tar.xz)
|
||||
set(FLAC_HASH 91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f)
|
||||
set(FLAC_HASH 213e82bd716c9de6db2f98bcadbc4c24c7e2efe8c75939a1a84e28539c4e1748)
|
||||
|
||||
set(VPX_VERSION 1.7.0)
|
||||
set(VPX_VERSION 1.8.2)
|
||||
set(VPX_URI https://github.com/webmproject/libvpx/archive/v${VPX_VERSION}/libvpx-v${VPX_VERSION}.tar.gz)
|
||||
set(VPX_HASH 1fec931eb5c94279ad219a5b6e0202358e94a93a90cfb1603578c326abfc1238)
|
||||
set(VPX_HASH 8735d9fcd1a781ae6917f28f239a8aa358ce4864ba113ea18af4bb2dc8b474ac)
|
||||
|
||||
set(OPUS_VERSION 1.3.1)
|
||||
set(OPUS_URI https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz)
|
||||
set(OPUS_HASH 65b58e1e25b2a114157014736a3d9dfeaad8d41be1c8179866f144a2fb44ff9d)
|
||||
|
||||
set(X264_URI http://download.videolan.org/pub/videolan/x264/snapshots/x264-snapshot-20180811-2245-stable.tar.bz2)
|
||||
set(X264_HASH ae8a868a0e236a348b35d79f3ee80294b169d1195408b689f9851383661ed7aa)
|
||||
set(X264_URI https://code.videolan.org/videolan/x264/-/archive/master/x264-33f9e1474613f59392be5ab6a7e7abf60fa63622.tar.gz)
|
||||
set(X264_HASH 300dfb5b6c35722516f168868ce9419252a9e9eb77a05d82c9cede925b691bd6)
|
||||
|
||||
set(XVIDCORE_VERSION 1.3.5)
|
||||
set(XVIDCORE_URI http://downloads.xvid.org/downloads/xvidcore-${XVIDCORE_VERSION}.tar.gz)
|
||||
set(XVIDCORE_HASH 165ba6a2a447a8375f7b06db5a3c91810181f2898166e7c8137401d7fc894cf0)
|
||||
set(XVIDCORE_VERSION 1.3.7)
|
||||
set(XVIDCORE_URI https://downloads.xvid.com/downloads/xvidcore-${XVIDCORE_VERSION}.tar.gz)
|
||||
set(XVIDCORE_HASH abbdcbd39555691dd1c9b4d08f0a031376a3b211652c0d8b3b8aa9be1303ce2d)
|
||||
|
||||
# This has to be in sync with the version in blenders /extern folder.
|
||||
set(OPENJPEG_VERSION 2.3.0)
|
||||
@@ -206,13 +206,9 @@ set(OPENJPEG_SHORT_VERSION 2.3)
|
||||
set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/66297f07a43.zip)
|
||||
set(OPENJPEG_HASH 8242b18d908c7c42174e4231a741cfa7ce7c26b6ed5c9644feb9df7b3054310b)
|
||||
|
||||
set(FAAD_VERSION 2-2.8.8)
|
||||
set(FAAD_URI http://downloads.sourceforge.net/faac/faad${FAAD_VERSION}.tar.gz)
|
||||
set(FAAD_HASH 28f6116efdbe9378269f8a6221767d1f)
|
||||
|
||||
set(FFMPEG_VERSION 4.0.2)
|
||||
set(FFMPEG_VERSION 4.2.3)
|
||||
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||
set(FFMPEG_HASH 5576e8a22f80b6a336db39808f427cfb)
|
||||
set(FFMPEG_HASH 695fad11f3baf27784e24cb0e977b65a)
|
||||
|
||||
set(FFTW_VERSION 3.3.8)
|
||||
set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
|
||||
@@ -319,6 +315,6 @@ set(MESA_VERSION 18.3.1)
|
||||
set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa//mesa-${MESA_VERSION}.tar.xz)
|
||||
set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be)
|
||||
|
||||
set(XR_OPENXR_SDK_VERSION 1.0.6)
|
||||
set(XR_OPENXR_SDK_VERSION 1.0.8)
|
||||
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
|
||||
set(XR_OPENXR_SDK_HASH 21daea7c3bfec365298d779a0e19caa1)
|
||||
set(XR_OPENXR_SDK_HASH c6de63d2e0f9029aa58dfa97cad8ce07)
|
||||
|
@@ -18,9 +18,6 @@
|
||||
|
||||
if(WIN32)
|
||||
set(X264_EXTRA_ARGS --enable-win32thread --cross-prefix=${MINGW_HOST}- --host=${MINGW_HOST})
|
||||
set(X264_PATCH_CMD ${PATCH_CMD} --verbose -p 1 -N -d ${BUILD_DIR}/x264/src/external_x264 < ${PATCH_DIR}/x264.diff)
|
||||
else()
|
||||
set(X264_PATCH_CMD echo .)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -29,7 +26,6 @@ ExternalProject_Add(external_x264
|
||||
DOWNLOAD_DIR ${DOWNLOAD_DIR}
|
||||
URL_HASH SHA256=${X264_HASH}
|
||||
PREFIX ${BUILD_DIR}/x264
|
||||
PATCH_COMMAND ${X264_PATCH_CMD}
|
||||
CONFIGURE_COMMAND ${CONFIGURE_ENV} && cd ${BUILD_DIR}/x264/src/external_x264/ && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/x264
|
||||
--enable-static
|
||||
--enable-pic
|
||||
|
@@ -1,13 +0,0 @@
|
||||
diff -Naur external_openal_original/CMakeLists.txt external_openal/CMakeLists.txt
|
||||
--- external_openal_original/CMakeLists.txt 2016-01-24 20:12:39 -0700
|
||||
+++ external_openal/CMakeLists.txt 2018-06-02 12:16:52 -0600
|
||||
@@ -885,7 +885,8 @@
|
||||
OPTION(ALSOFT_REQUIRE_MMDEVAPI "Require MMDevApi backend" OFF)
|
||||
IF(HAVE_WINDOWS_H)
|
||||
# Check MMSystem backend
|
||||
- CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0502)
|
||||
+ set(CMAKE_REQUIRED_FLAGS "-D_WIN32_WINNT=0x0502")
|
||||
+ CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H)
|
||||
IF(HAVE_MMSYSTEM_H)
|
||||
CHECK_SHARED_FUNCTION_EXISTS(waveOutOpen "windows.h;mmsystem.h" winmm "" HAVE_LIBWINMM)
|
||||
IF(HAVE_LIBWINMM)
|
@@ -1,22 +0,0 @@
|
||||
--- x264-snapshot-20180811-2245-stable\configure 2018-08-11 14:45:05 -0600
|
||||
+++ external_x264\configure 2018-08-11 23:51:35 -0600
|
||||
@@ -396,7 +396,7 @@
|
||||
# list of all preprocessor HAVE values we can define
|
||||
CONFIG_HAVE="MALLOC_H ALTIVEC ALTIVEC_H MMX ARMV6 ARMV6T2 NEON BEOSTHREAD POSIXTHREAD WIN32THREAD THREAD LOG2F SWSCALE \
|
||||
LAVF FFMS GPAC AVS GPL VECTOREXT INTERLACED CPU_COUNT OPENCL THP LSMASH X86_INLINE_ASM AS_FUNC INTEL_DISPATCHER \
|
||||
- MSA MMAP WINRT VSX ARM_INLINE_ASM STRTOK_R BITDEPTH8 BITDEPTH10"
|
||||
+ MSA MMAP WINRT VSX ARM_INLINE_ASM BITDEPTH8 BITDEPTH10"
|
||||
|
||||
# parse options
|
||||
|
||||
@@ -1071,10 +1071,6 @@
|
||||
define HAVE_LOG2F
|
||||
fi
|
||||
|
||||
-if cc_check 'string.h' '' 'strtok_r(0, 0, 0);' ; then
|
||||
- define HAVE_STRTOK_R
|
||||
-fi
|
||||
-
|
||||
if [ "$SYS" != "WINDOWS" ] && cpp_check "sys/mman.h unistd.h" "" "defined(MAP_PRIVATE)"; then
|
||||
define HAVE_MMAP
|
||||
fi
|
@@ -52,6 +52,7 @@ set(WITH_OPENVDB OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_SDL OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_TBB OFF CACHE BOOL "" FORCE)
|
||||
set(WITH_USD OFF CACHE BOOL "" FORCE)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE)
|
||||
|
@@ -190,7 +190,7 @@ if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /JMC")
|
||||
endif()
|
||||
|
||||
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /SUBSYSTEM:CONSOLE /STACK:2097152 ")
|
||||
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /SUBSYSTEM:CONSOLE /STACK:2097152")
|
||||
set(PLATFORM_LINKFLAGS_RELEASE "/NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:libcmtd.lib /NODEFAULTLIB:msvcrtd.lib")
|
||||
set(PLATFORM_LINKFLAGS_DEBUG "${PLATFORM_LINKFLAGS_DEBUG} /IGNORE:4099 /NODEFAULTLIB:libcmt.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libcmtd.lib")
|
||||
|
||||
|
@@ -1,2 +1,2 @@
|
||||
Sphinx==1.8.5
|
||||
sphinx_rtd_theme==0.4.3
|
||||
Sphinx==3.0.3
|
||||
sphinx_rtd_theme==0.5.0rc1
|
||||
|
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
2
extern/mantaflow/preprocessed/gitinfo.h
vendored
@@ -1,3 +1,3 @@
|
||||
|
||||
|
||||
#define MANTA_GIT_VERSION "commit b4a2742bd743e2913fba94dd35846042e2650212"
|
||||
#define MANTA_GIT_VERSION "commit b61bf9efa7a1d8ca98635076a7e9f2c4dacb2914"
|
||||
|
62
extern/mantaflow/preprocessed/particle.h
vendored
62
extern/mantaflow/preprocessed/particle.h
vendored
@@ -469,6 +469,7 @@ template<class S> class ParticleSystem : public ParticleBase {
|
||||
const int integrationMode,
|
||||
const bool deleteInObstacle = true,
|
||||
const bool stopInObstacle = true,
|
||||
const bool skipNew = false,
|
||||
const ParticleDataImpl<int> *ptype = NULL,
|
||||
const int exclude = 0);
|
||||
static PyObject *_W_9(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
|
||||
@@ -486,13 +487,20 @@ template<class S> class ParticleSystem : public ParticleBase {
|
||||
const int integrationMode = _args.get<int>("integrationMode", 2, &_lock);
|
||||
const bool deleteInObstacle = _args.getOpt<bool>("deleteInObstacle", 3, true, &_lock);
|
||||
const bool stopInObstacle = _args.getOpt<bool>("stopInObstacle", 4, true, &_lock);
|
||||
const bool skipNew = _args.getOpt<bool>("skipNew", 5, false, &_lock);
|
||||
const ParticleDataImpl<int> *ptype = _args.getPtrOpt<ParticleDataImpl<int>>(
|
||||
"ptype", 5, NULL, &_lock);
|
||||
const int exclude = _args.getOpt<int>("exclude", 6, 0, &_lock);
|
||||
"ptype", 6, NULL, &_lock);
|
||||
const int exclude = _args.getOpt<int>("exclude", 7, 0, &_lock);
|
||||
pbo->_args.copy(_args);
|
||||
_retval = getPyNone();
|
||||
pbo->advectInGrid(
|
||||
flags, vel, integrationMode, deleteInObstacle, stopInObstacle, ptype, exclude);
|
||||
pbo->advectInGrid(flags,
|
||||
vel,
|
||||
integrationMode,
|
||||
deleteInObstacle,
|
||||
stopInObstacle,
|
||||
skipNew,
|
||||
ptype,
|
||||
exclude);
|
||||
pbo->_args.check();
|
||||
}
|
||||
pbFinalizePlugin(pbo->getParent(), "ParticleSystem::advectInGrid", !noTiming);
|
||||
@@ -1863,6 +1871,7 @@ template<class S> struct _GridAdvectKernel : public KernelBase {
|
||||
const Real dt,
|
||||
const bool deleteInObstacle,
|
||||
const bool stopInObstacle,
|
||||
const bool skipNew,
|
||||
const ParticleDataImpl<int> *ptype,
|
||||
const int exclude,
|
||||
std::vector<Vec3> &u)
|
||||
@@ -1873,6 +1882,7 @@ template<class S> struct _GridAdvectKernel : public KernelBase {
|
||||
dt(dt),
|
||||
deleteInObstacle(deleteInObstacle),
|
||||
stopInObstacle(stopInObstacle),
|
||||
skipNew(skipNew),
|
||||
ptype(ptype),
|
||||
exclude(exclude),
|
||||
u(u)
|
||||
@@ -1885,11 +1895,13 @@ template<class S> struct _GridAdvectKernel : public KernelBase {
|
||||
const Real dt,
|
||||
const bool deleteInObstacle,
|
||||
const bool stopInObstacle,
|
||||
const bool skipNew,
|
||||
const ParticleDataImpl<int> *ptype,
|
||||
const int exclude,
|
||||
std::vector<Vec3> &u) const
|
||||
{
|
||||
if ((p[idx].flag & ParticleBase::PDELETE) || (ptype && ((*ptype)[idx] & exclude))) {
|
||||
if ((p[idx].flag & ParticleBase::PDELETE) || (ptype && ((*ptype)[idx] & exclude)) ||
|
||||
(skipNew && (p[idx].flag & ParticleBase::PNEW))) {
|
||||
u[idx] = 0.;
|
||||
return;
|
||||
}
|
||||
@@ -1910,7 +1922,7 @@ template<class S> struct _GridAdvectKernel : public KernelBase {
|
||||
void operator()(const tbb::blocked_range<IndexInt> &__r) const
|
||||
{
|
||||
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
|
||||
op(idx, p, vel, flags, dt, deleteInObstacle, stopInObstacle, ptype, exclude, u);
|
||||
op(idx, p, vel, flags, dt, deleteInObstacle, stopInObstacle, skipNew, ptype, exclude, u);
|
||||
}
|
||||
void run()
|
||||
{
|
||||
@@ -1922,6 +1934,7 @@ template<class S> struct _GridAdvectKernel : public KernelBase {
|
||||
const Real dt;
|
||||
const bool deleteInObstacle;
|
||||
const bool stopInObstacle;
|
||||
const bool skipNew;
|
||||
const ParticleDataImpl<int> *ptype;
|
||||
const int exclude;
|
||||
std::vector<Vec3> &u;
|
||||
@@ -1933,6 +1946,7 @@ template<class S> struct GridAdvectKernel : public KernelBase {
|
||||
const Real dt,
|
||||
const bool deleteInObstacle,
|
||||
const bool stopInObstacle,
|
||||
const bool skipNew,
|
||||
const ParticleDataImpl<int> *ptype,
|
||||
const int exclude)
|
||||
: KernelBase(p.size()),
|
||||
@@ -1943,6 +1957,7 @@ template<class S> struct GridAdvectKernel : public KernelBase {
|
||||
dt,
|
||||
deleteInObstacle,
|
||||
stopInObstacle,
|
||||
skipNew,
|
||||
ptype,
|
||||
exclude,
|
||||
u),
|
||||
@@ -1952,6 +1967,7 @@ template<class S> struct GridAdvectKernel : public KernelBase {
|
||||
dt(dt),
|
||||
deleteInObstacle(deleteInObstacle),
|
||||
stopInObstacle(stopInObstacle),
|
||||
skipNew(skipNew),
|
||||
ptype(ptype),
|
||||
exclude(exclude),
|
||||
u((size))
|
||||
@@ -2001,16 +2017,21 @@ template<class S> struct GridAdvectKernel : public KernelBase {
|
||||
return stopInObstacle;
|
||||
}
|
||||
typedef bool type5;
|
||||
inline const ParticleDataImpl<int> *getArg6()
|
||||
inline const bool &getArg6()
|
||||
{
|
||||
return skipNew;
|
||||
}
|
||||
typedef bool type6;
|
||||
inline const ParticleDataImpl<int> *getArg7()
|
||||
{
|
||||
return ptype;
|
||||
}
|
||||
typedef ParticleDataImpl<int> type6;
|
||||
inline const int &getArg7()
|
||||
typedef ParticleDataImpl<int> type7;
|
||||
inline const int &getArg8()
|
||||
{
|
||||
return exclude;
|
||||
}
|
||||
typedef int type7;
|
||||
typedef int type8;
|
||||
void runMessage()
|
||||
{
|
||||
debMsg("Executing kernel GridAdvectKernel ", 3);
|
||||
@@ -2025,6 +2046,7 @@ template<class S> struct GridAdvectKernel : public KernelBase {
|
||||
const Real dt;
|
||||
const bool deleteInObstacle;
|
||||
const bool stopInObstacle;
|
||||
const bool skipNew;
|
||||
const ParticleDataImpl<int> *ptype;
|
||||
const int exclude;
|
||||
std::vector<Vec3> u;
|
||||
@@ -2195,6 +2217,7 @@ void ParticleSystem<S>::advectInGrid(const FlagGrid &flags,
|
||||
const int integrationMode,
|
||||
const bool deleteInObstacle,
|
||||
const bool stopInObstacle,
|
||||
const bool skipNew,
|
||||
const ParticleDataImpl<int> *ptype,
|
||||
const int exclude)
|
||||
{
|
||||
@@ -2208,8 +2231,15 @@ void ParticleSystem<S>::advectInGrid(const FlagGrid &flags,
|
||||
}
|
||||
|
||||
// update positions
|
||||
GridAdvectKernel<S> kernel(
|
||||
mData, vel, flags, getParent()->getDt(), deleteInObstacle, stopInObstacle, ptype, exclude);
|
||||
GridAdvectKernel<S> kernel(mData,
|
||||
vel,
|
||||
flags,
|
||||
getParent()->getDt(),
|
||||
deleteInObstacle,
|
||||
stopInObstacle,
|
||||
skipNew,
|
||||
ptype,
|
||||
exclude);
|
||||
integratePointSet(kernel, integrationMode);
|
||||
|
||||
if (!deleteInObstacle) {
|
||||
@@ -2438,15 +2468,15 @@ template<class S> void ParticleSystem<S>::compress()
|
||||
//! insert buffered positions as new particles, update additional particle data
|
||||
template<class S> void ParticleSystem<S>::insertBufferedParticles()
|
||||
{
|
||||
// clear new flag everywhere
|
||||
for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
|
||||
mData[i].flag &= ~PNEW;
|
||||
|
||||
if (mNewBufferPos.size() == 0)
|
||||
return;
|
||||
IndexInt newCnt = mData.size();
|
||||
resizeAll(newCnt + mNewBufferPos.size());
|
||||
|
||||
// clear new flag everywhere
|
||||
for (IndexInt i = 0; i < (IndexInt)mData.size(); ++i)
|
||||
mData[i].flag &= ~PNEW;
|
||||
|
||||
for (IndexInt i = 0; i < (IndexInt)mNewBufferPos.size(); ++i) {
|
||||
int flag = (mNewBufferFlag.size() > 0) ? mNewBufferFlag[i] : 0;
|
||||
// note, other fields are not initialized here...
|
||||
|
@@ -82,8 +82,8 @@ class CyclesRender(bpy.types.RenderEngine):
|
||||
def render(self, depsgraph):
|
||||
engine.render(self, depsgraph)
|
||||
|
||||
def bake(self, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result):
|
||||
engine.bake(self, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result)
|
||||
def bake(self, depsgraph, obj, pass_type, pass_filter, width, height):
|
||||
engine.bake(self, depsgraph, obj, pass_type, pass_filter, width, height)
|
||||
|
||||
# viewport render
|
||||
def view_update(self, context, depsgraph):
|
||||
|
@@ -168,11 +168,11 @@ def render(engine, depsgraph):
|
||||
_cycles.render(engine.session, depsgraph.as_pointer())
|
||||
|
||||
|
||||
def bake(engine, depsgraph, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result):
|
||||
def bake(engine, depsgraph, obj, pass_type, pass_filter, width, height):
|
||||
import _cycles
|
||||
session = getattr(engine, "session", None)
|
||||
if session is not None:
|
||||
_cycles.bake(engine.session, depsgraph.as_pointer(), obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer())
|
||||
_cycles.bake(engine.session, depsgraph.as_pointer(), obj.as_pointer(), pass_type, pass_filter, width, height)
|
||||
|
||||
|
||||
def reset(engine, data, depsgraph):
|
||||
|
@@ -1907,10 +1907,15 @@ class CYCLES_RENDER_PT_bake_selected_to_active(CyclesButtonsPanel, Panel):
|
||||
|
||||
col.prop(cbk, "use_cage", text="Cage")
|
||||
if cbk.use_cage:
|
||||
col.prop(cbk, "cage_extrusion", text="Extrusion")
|
||||
col.prop(cbk, "cage_object", text="Cage Object")
|
||||
col.prop(cbk, "cage_object")
|
||||
col = layout.column()
|
||||
col.prop(cbk, "cage_extrusion")
|
||||
col.active = cbk.cage_object is None
|
||||
else:
|
||||
col.prop(cbk, "cage_extrusion", text="Ray Distance")
|
||||
col.prop(cbk, "cage_extrusion", text="Extrusion")
|
||||
|
||||
col = layout.column()
|
||||
col.prop(cbk, "max_ray_distance")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_bake_output(CyclesButtonsPanel, Panel):
|
||||
|
@@ -460,9 +460,12 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
|
||||
sync_objects(b_depsgraph, b_v3d, 0.0f);
|
||||
}
|
||||
|
||||
/* always sample these times for camera motion */
|
||||
motion_times.insert(-1.0f);
|
||||
motion_times.insert(1.0f);
|
||||
/* Insert motion times from camera. Motion times from other objects
|
||||
* have already been added in a sync_objects call. */
|
||||
uint camera_motion_steps = object_motion_steps(b_cam, b_cam);
|
||||
for (size_t step = 0; step < camera_motion_steps; step++) {
|
||||
motion_times.insert(scene->camera->motion_time(step));
|
||||
}
|
||||
|
||||
/* note iteration over motion_times set happens in sorted order */
|
||||
foreach (float relative_time, motion_times) {
|
||||
@@ -487,10 +490,8 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
|
||||
b_engine.frame_set(frame, subframe);
|
||||
python_thread_state_save(python_thread_state);
|
||||
|
||||
/* sync camera, only supports two times at the moment */
|
||||
if (relative_time == -1.0f || relative_time == 1.0f) {
|
||||
sync_camera_motion(b_render, b_cam, width, height, relative_time);
|
||||
}
|
||||
/* Syncs camera motion if relative_time is one of the camera's motion times. */
|
||||
sync_camera_motion(b_render, b_cam, width, height, relative_time);
|
||||
|
||||
/* sync object */
|
||||
sync_objects(b_depsgraph, b_v3d, relative_time);
|
||||
|
@@ -298,22 +298,18 @@ static PyObject *render_func(PyObject * /*self*/, PyObject *args)
|
||||
static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
PyObject *pysession, *pydepsgraph, *pyobject;
|
||||
PyObject *pypixel_array, *pyresult;
|
||||
const char *pass_type;
|
||||
int num_pixels, depth, object_id, pass_filter;
|
||||
int pass_filter, width, height;
|
||||
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"OOOsiiOiiO",
|
||||
"OOOsiii",
|
||||
&pysession,
|
||||
&pydepsgraph,
|
||||
&pyobject,
|
||||
&pass_type,
|
||||
&pass_filter,
|
||||
&object_id,
|
||||
&pypixel_array,
|
||||
&num_pixels,
|
||||
&depth,
|
||||
&pyresult))
|
||||
&width,
|
||||
&height))
|
||||
return NULL;
|
||||
|
||||
BlenderSession *session = (BlenderSession *)PyLong_AsVoidPtr(pysession);
|
||||
@@ -326,23 +322,9 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args)
|
||||
RNA_id_pointer_create((ID *)PyLong_AsVoidPtr(pyobject), &objectptr);
|
||||
BL::Object b_object(objectptr);
|
||||
|
||||
void *b_result = PyLong_AsVoidPtr(pyresult);
|
||||
|
||||
PointerRNA bakepixelptr;
|
||||
RNA_pointer_create(NULL, &RNA_BakePixel, PyLong_AsVoidPtr(pypixel_array), &bakepixelptr);
|
||||
BL::BakePixel b_bake_pixel(bakepixelptr);
|
||||
|
||||
python_thread_state_save(&session->python_thread_state);
|
||||
|
||||
session->bake(b_depsgraph,
|
||||
b_object,
|
||||
pass_type,
|
||||
pass_filter,
|
||||
object_id,
|
||||
b_bake_pixel,
|
||||
(size_t)num_pixels,
|
||||
depth,
|
||||
(float *)b_result);
|
||||
session->bake(b_depsgraph, b_object, pass_type, pass_filter, width, height);
|
||||
|
||||
python_thread_state_restore(&session->python_thread_state);
|
||||
|
||||
|
@@ -247,9 +247,7 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
|
||||
|
||||
void BlenderSession::free_session()
|
||||
{
|
||||
if (sync)
|
||||
delete sync;
|
||||
|
||||
delete sync;
|
||||
delete session;
|
||||
}
|
||||
|
||||
@@ -317,6 +315,7 @@ static void end_render_result(BL::RenderEngine &b_engine,
|
||||
|
||||
void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
|
||||
bool do_update_only,
|
||||
bool do_read_only,
|
||||
bool highlight)
|
||||
{
|
||||
int x = rtile.x - session->tile_manager.params.full_x;
|
||||
@@ -342,7 +341,23 @@ void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
|
||||
|
||||
BL::RenderLayer b_rlay = *b_single_rlay;
|
||||
|
||||
if (do_update_only) {
|
||||
if (do_read_only) {
|
||||
/* copy each pass */
|
||||
BL::RenderLayer::passes_iterator b_iter;
|
||||
|
||||
for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
|
||||
BL::RenderPass b_pass(*b_iter);
|
||||
|
||||
/* find matching pass type */
|
||||
PassType pass_type = BlenderSync::get_pass_type(b_pass);
|
||||
int components = b_pass.channels();
|
||||
|
||||
rtile.buffers->set_pass_rect(pass_type, components, (float *)b_pass.rect());
|
||||
}
|
||||
|
||||
end_render_result(b_engine, b_rr, false, false, false);
|
||||
}
|
||||
else if (do_update_only) {
|
||||
/* Sample would be zero at initial tile update, which is only needed
|
||||
* to tag tile form blender side as IN PROGRESS for proper highlight
|
||||
* no buffers should be sent to blender yet. For denoise we also
|
||||
@@ -362,9 +377,14 @@ void BlenderSession::do_write_update_render_tile(RenderTile &rtile,
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderSession::read_render_tile(RenderTile &rtile)
|
||||
{
|
||||
do_write_update_render_tile(rtile, false, true, false);
|
||||
}
|
||||
|
||||
void BlenderSession::write_render_tile(RenderTile &rtile)
|
||||
{
|
||||
do_write_update_render_tile(rtile, false, false);
|
||||
do_write_update_render_tile(rtile, false, false, false);
|
||||
}
|
||||
|
||||
void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
|
||||
@@ -374,9 +394,9 @@ void BlenderSession::update_render_tile(RenderTile &rtile, bool highlight)
|
||||
* would need to be investigated a bit further, but for now shall be fine
|
||||
*/
|
||||
if (!b_engine.is_preview())
|
||||
do_write_update_render_tile(rtile, true, highlight);
|
||||
do_write_update_render_tile(rtile, true, false, highlight);
|
||||
else
|
||||
do_write_update_render_tile(rtile, false, false);
|
||||
do_write_update_render_tile(rtile, false, false, false);
|
||||
}
|
||||
|
||||
static void add_cryptomatte_layer(BL::RenderResult &b_rr, string name, string manifest)
|
||||
@@ -593,25 +613,6 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void populate_bake_data(BakeData *data,
|
||||
const int object_id,
|
||||
BL::BakePixel &pixel_array,
|
||||
const int num_pixels)
|
||||
{
|
||||
BL::BakePixel bp = pixel_array;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < num_pixels; i++) {
|
||||
if (bp.object_id() == object_id) {
|
||||
data->set(i, bp.primitive_id(), bp.uv(), bp.du_dx(), bp.du_dy(), bp.dv_dx(), bp.dv_dy());
|
||||
}
|
||||
else {
|
||||
data->set_null(i);
|
||||
}
|
||||
bp = bp.next();
|
||||
}
|
||||
}
|
||||
|
||||
static int bake_pass_filter_get(const int pass_filter)
|
||||
{
|
||||
int flag = BAKE_FILTER_NONE;
|
||||
@@ -642,43 +643,26 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
|
||||
BL::Object &b_object,
|
||||
const string &pass_type,
|
||||
const int pass_filter,
|
||||
const int object_id,
|
||||
BL::BakePixel &pixel_array,
|
||||
const size_t num_pixels,
|
||||
const int /*depth*/,
|
||||
float result[])
|
||||
const int bake_width,
|
||||
const int bake_height)
|
||||
{
|
||||
b_depsgraph = b_depsgraph_;
|
||||
|
||||
ShaderEvalType shader_type = get_shader_type(pass_type);
|
||||
|
||||
/* Set baking flag in advance, so kernel loading can check if we need
|
||||
* any baking capabilities.
|
||||
*/
|
||||
scene->bake_manager->set_baking(true);
|
||||
|
||||
/* ensure kernels are loaded before we do any scene updates */
|
||||
session->load_kernels();
|
||||
|
||||
if (shader_type == SHADER_EVAL_UV) {
|
||||
/* force UV to be available */
|
||||
Pass::add(PASS_UV, scene->film->passes);
|
||||
}
|
||||
|
||||
int bake_pass_filter = bake_pass_filter_get(pass_filter);
|
||||
bake_pass_filter = BakeManager::shader_type_to_pass_filter(shader_type, bake_pass_filter);
|
||||
|
||||
/* force use_light_pass to be true if we bake more than just colors */
|
||||
if (bake_pass_filter & ~BAKE_FILTER_COLOR) {
|
||||
Pass::add(PASS_LIGHT, scene->film->passes);
|
||||
}
|
||||
/* Initialize bake manager, before we load the baking kernels. */
|
||||
scene->bake_manager->set(scene, b_object.name(), shader_type, bake_pass_filter);
|
||||
|
||||
/* create device and update scene */
|
||||
scene->film->tag_update(scene);
|
||||
scene->integrator->tag_update(scene);
|
||||
/* Passes are identified by name, so in order to return the combined pass we need to set the
|
||||
* name. */
|
||||
Pass::add(PASS_COMBINED, scene->film->passes, "Combined");
|
||||
|
||||
session->read_bake_tile_cb = function_bind(&BlenderSession::read_render_tile, this, _1);
|
||||
session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
|
||||
|
||||
if (!session->progress.get_cancel()) {
|
||||
/* update scene */
|
||||
/* Sync scene. */
|
||||
BL::Object b_camera_override(b_engine.camera_override());
|
||||
sync->sync_camera(b_render, b_camera_override, width, height, "");
|
||||
sync->sync_data(
|
||||
@@ -686,75 +670,43 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_,
|
||||
builtin_images_load();
|
||||
}
|
||||
|
||||
BakeData *bake_data = NULL;
|
||||
/* Object might have been disabled for rendering or excluded in some
|
||||
* other way, in that case Blender will report a warning afterwards. */
|
||||
bool object_found = false;
|
||||
foreach (Object *ob, scene->objects) {
|
||||
if (ob->name == b_object.name()) {
|
||||
object_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!session->progress.get_cancel()) {
|
||||
/* get buffer parameters */
|
||||
if (object_found && !session->progress.get_cancel()) {
|
||||
/* Get session and buffer parameters. */
|
||||
SessionParams session_params = BlenderSync::get_session_params(
|
||||
b_engine, b_userpref, b_scene, background);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(
|
||||
b_scene, b_render, b_v3d, b_rv3d, scene->camera, width, height);
|
||||
session_params.progressive_refine = false;
|
||||
|
||||
scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y());
|
||||
BufferParams buffer_params;
|
||||
buffer_params.width = bake_width;
|
||||
buffer_params.height = bake_height;
|
||||
buffer_params.passes = scene->film->passes;
|
||||
|
||||
/* set number of samples */
|
||||
/* Update session. */
|
||||
session->tile_manager.set_samples(session_params.samples);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
session->update_scene();
|
||||
|
||||
/* find object index. todo: is arbitrary - copied from mesh_displace.cpp */
|
||||
size_t object_index = OBJECT_NONE;
|
||||
int tri_offset = 0;
|
||||
|
||||
for (size_t i = 0; i < scene->objects.size(); i++) {
|
||||
const Object *object = scene->objects[i];
|
||||
const Geometry *geom = object->geometry;
|
||||
if (object->name == b_object.name() && geom->type == Geometry::MESH) {
|
||||
const Mesh *mesh = static_cast<const Mesh *>(geom);
|
||||
object_index = i;
|
||||
tri_offset = mesh->prim_offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Object might have been disabled for rendering or excluded in some
|
||||
* other way, in that case Blender will report a warning afterwards. */
|
||||
if (object_index != OBJECT_NONE) {
|
||||
int object = object_index;
|
||||
|
||||
bake_data = scene->bake_manager->init(object, tri_offset, num_pixels);
|
||||
populate_bake_data(bake_data, object_id, pixel_array, num_pixels);
|
||||
}
|
||||
|
||||
/* set number of samples */
|
||||
session->tile_manager.set_samples(session_params.samples);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
session->update_scene();
|
||||
|
||||
session->progress.set_update_callback(
|
||||
function_bind(&BlenderSession::update_bake_progress, this));
|
||||
}
|
||||
|
||||
/* Perform bake. Check cancel to avoid crash with incomplete scene data. */
|
||||
if (!session->progress.get_cancel() && bake_data) {
|
||||
scene->bake_manager->bake(scene->device,
|
||||
&scene->dscene,
|
||||
scene,
|
||||
session->progress,
|
||||
shader_type,
|
||||
bake_pass_filter,
|
||||
bake_data,
|
||||
result);
|
||||
if (object_found && !session->progress.get_cancel()) {
|
||||
session->start();
|
||||
session->wait();
|
||||
}
|
||||
|
||||
/* free all memory used (host and device), so we wouldn't leave render
|
||||
* engine with extra memory allocated
|
||||
*/
|
||||
|
||||
session->device_free();
|
||||
|
||||
delete sync;
|
||||
sync = NULL;
|
||||
session->read_bake_tile_cb = function_null;
|
||||
session->write_render_tile_cb = function_null;
|
||||
}
|
||||
|
||||
void BlenderSession::do_write_update_render_result(BL::RenderLayer &b_rlay,
|
||||
|
@@ -66,14 +66,12 @@ class BlenderSession {
|
||||
BL::Object &b_object,
|
||||
const string &pass_type,
|
||||
const int custom_flag,
|
||||
const int object_id,
|
||||
BL::BakePixel &pixel_array,
|
||||
const size_t num_pixels,
|
||||
const int depth,
|
||||
float pixels[]);
|
||||
const int bake_width,
|
||||
const int bake_height);
|
||||
|
||||
void write_render_result(BL::RenderLayer &b_rlay, RenderTile &rtile);
|
||||
void write_render_tile(RenderTile &rtile);
|
||||
void read_render_tile(RenderTile &rtile);
|
||||
|
||||
/* update functions are used to update display buffer only after sample was rendered
|
||||
* only needed for better visual feedback */
|
||||
@@ -155,7 +153,10 @@ class BlenderSession {
|
||||
void do_write_update_render_result(BL::RenderLayer &b_rlay,
|
||||
RenderTile &rtile,
|
||||
bool do_update_only);
|
||||
void do_write_update_render_tile(RenderTile &rtile, bool do_update_only, bool highlight);
|
||||
void do_write_update_render_tile(RenderTile &rtile,
|
||||
bool do_update_only,
|
||||
bool do_read_only,
|
||||
bool highlight);
|
||||
|
||||
void builtin_images_load();
|
||||
|
||||
|
@@ -384,16 +384,16 @@ static ShaderNode *add_node(Scene *scene,
|
||||
|
||||
switch (b_aniso_node.distribution()) {
|
||||
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfAnisotropic::distribution_MULTI_GGX:
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID;
|
||||
aniso->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
break;
|
||||
case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
|
||||
aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
|
||||
aniso->distribution = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1231,12 +1231,11 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
|
||||
Shader *shader;
|
||||
|
||||
/* test if we need to sync */
|
||||
if (shader_map.add_or_update(&shader, b_mat) || shader->need_sync_object || update_all) {
|
||||
if (shader_map.add_or_update(&shader, b_mat) || update_all) {
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
shader->name = b_mat.name().c_str();
|
||||
shader->pass_id = b_mat.pass_index();
|
||||
shader->need_sync_object = false;
|
||||
|
||||
/* create nodes */
|
||||
if (b_mat.use_nodes() && b_mat.node_tree()) {
|
||||
|
@@ -85,8 +85,6 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
/* Sync recalc flags from blender to cycles. Actual update is done separate,
|
||||
* so we can do it later on if doing it immediate is not suitable. */
|
||||
|
||||
bool has_updated_objects = b_depsgraph.id_type_updated(BL::DriverTarget::id_type_OBJECT);
|
||||
|
||||
if (experimental) {
|
||||
/* Mark all meshes as needing to be exported again if dicing changed. */
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
@@ -189,19 +187,6 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d
|
||||
if (viewport_parameters.modified(new_viewport_parameters)) {
|
||||
world_recalc = true;
|
||||
}
|
||||
|
||||
/* Updates shader with object dependency if objects changed. */
|
||||
if (has_updated_objects) {
|
||||
if (scene->default_background->has_object_dependency) {
|
||||
world_recalc = true;
|
||||
}
|
||||
|
||||
foreach (Shader *shader, scene->shaders) {
|
||||
if (shader->has_object_dependency) {
|
||||
shader->need_sync_object = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
||||
@@ -496,6 +481,9 @@ PassType BlenderSync::get_pass_type(BL::RenderPass &b_pass)
|
||||
MAP_PASS("AO", PASS_AO);
|
||||
MAP_PASS("Shadow", PASS_SHADOW);
|
||||
|
||||
MAP_PASS("BakePrimitive", PASS_BAKE_PRIMITIVE);
|
||||
MAP_PASS("BakeDifferential", PASS_BAKE_DIFFERENTIAL);
|
||||
|
||||
#ifdef __KERNEL_DEBUG__
|
||||
MAP_PASS("Debug BVH Traversed Nodes", PASS_BVH_TRAVERSED_NODES);
|
||||
MAP_PASS("Debug BVH Traversed Instances", PASS_BVH_TRAVERSED_INSTANCES);
|
||||
|
@@ -34,15 +34,13 @@ CCL_NAMESPACE_BEGIN
|
||||
/* TODO: verify this is not loading unnecessary attributes. */
|
||||
class BlenderSmokeLoader : public ImageLoader {
|
||||
public:
|
||||
BlenderSmokeLoader(const BL::Object &b_ob, AttributeStandard attribute)
|
||||
: b_ob(b_ob), attribute(attribute)
|
||||
BlenderSmokeLoader(BL::Object &b_ob, AttributeStandard attribute)
|
||||
: b_domain(object_fluid_gas_domain_find(b_ob)), b_mesh(b_ob.data()), attribute(attribute)
|
||||
{
|
||||
}
|
||||
|
||||
bool load_metadata(ImageMetaData &metadata) override
|
||||
{
|
||||
BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob);
|
||||
|
||||
if (!b_domain) {
|
||||
return false;
|
||||
}
|
||||
@@ -79,7 +77,6 @@ class BlenderSmokeLoader : public ImageLoader {
|
||||
/* Create a matrix to transform from object space to mesh texture space.
|
||||
* This does not work with deformations but that can probably only be done
|
||||
* well with a volume grid mapping of coordinates. */
|
||||
BL::Mesh b_mesh(b_ob.data());
|
||||
float3 loc, size;
|
||||
mesh_texture_space(b_mesh, loc, size);
|
||||
metadata.transform_3d = transform_translate(-loc) * transform_scale(size);
|
||||
@@ -90,9 +87,6 @@ class BlenderSmokeLoader : public ImageLoader {
|
||||
|
||||
bool load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool) override
|
||||
{
|
||||
/* smoke volume data */
|
||||
BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob);
|
||||
|
||||
if (!b_domain) {
|
||||
return false;
|
||||
}
|
||||
@@ -179,10 +173,11 @@ class BlenderSmokeLoader : public ImageLoader {
|
||||
bool equals(const ImageLoader &other) const override
|
||||
{
|
||||
const BlenderSmokeLoader &other_loader = (const BlenderSmokeLoader &)other;
|
||||
return b_ob == other_loader.b_ob && attribute == other_loader.attribute;
|
||||
return b_domain == other_loader.b_domain && attribute == other_loader.attribute;
|
||||
}
|
||||
|
||||
BL::Object b_ob;
|
||||
BL::FluidDomainSettings b_domain;
|
||||
BL::Mesh b_mesh;
|
||||
AttributeStandard attribute;
|
||||
};
|
||||
|
||||
|
@@ -223,7 +223,7 @@ class CUDADevice : public Device {
|
||||
CUdeviceptr d_wtile,
|
||||
CUstream stream = 0);
|
||||
|
||||
void path_trace(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles);
|
||||
void render(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles);
|
||||
|
||||
void film_convert(DeviceTask &task,
|
||||
device_ptr buffer,
|
||||
|
@@ -586,20 +586,23 @@ void CUDADevice::reserve_local_memory(const DeviceRequestedFeatures &requested_f
|
||||
cuMemGetInfo(&free_before, &total);
|
||||
|
||||
/* Get kernel function. */
|
||||
CUfunction cuPathTrace;
|
||||
CUfunction cuRender;
|
||||
|
||||
if (requested_features.use_integrator_branched) {
|
||||
cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
|
||||
if (requested_features.use_baking) {
|
||||
cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_bake"));
|
||||
}
|
||||
else if (requested_features.use_integrator_branched) {
|
||||
cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_branched_path_trace"));
|
||||
}
|
||||
else {
|
||||
cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
|
||||
cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_path_trace"));
|
||||
}
|
||||
|
||||
cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
|
||||
cuda_assert(cuFuncSetCacheConfig(cuRender, CU_FUNC_CACHE_PREFER_L1));
|
||||
|
||||
int min_blocks, num_threads_per_block;
|
||||
cuda_assert(cuOccupancyMaxPotentialBlockSize(
|
||||
&min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
|
||||
cuda_assert(
|
||||
cuOccupancyMaxPotentialBlockSize(&min_blocks, &num_threads_per_block, cuRender, NULL, 0, 0));
|
||||
|
||||
/* Launch kernel, using just 1 block appears sufficient to reserve
|
||||
* memory for all multiprocessors. It would be good to do this in
|
||||
@@ -609,7 +612,7 @@ void CUDADevice::reserve_local_memory(const DeviceRequestedFeatures &requested_f
|
||||
|
||||
void *args[] = {&d_work_tiles, &total_work_size};
|
||||
|
||||
cuda_assert(cuLaunchKernel(cuPathTrace, 1, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
|
||||
cuda_assert(cuLaunchKernel(cuRender, 1, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
|
||||
|
||||
cuda_assert(cuCtxSynchronize());
|
||||
|
||||
@@ -1780,9 +1783,7 @@ void CUDADevice::adaptive_sampling_post(RenderTile &rtile,
|
||||
0));
|
||||
}
|
||||
|
||||
void CUDADevice::path_trace(DeviceTask &task,
|
||||
RenderTile &rtile,
|
||||
device_vector<WorkTile> &work_tiles)
|
||||
void CUDADevice::render(DeviceTask &task, RenderTile &rtile, device_vector<WorkTile> &work_tiles)
|
||||
{
|
||||
scoped_timer timer(&rtile.buffers->render_time);
|
||||
|
||||
@@ -1790,21 +1791,24 @@ void CUDADevice::path_trace(DeviceTask &task,
|
||||
return;
|
||||
|
||||
CUDAContextScope scope(this);
|
||||
CUfunction cuPathTrace;
|
||||
CUfunction cuRender;
|
||||
|
||||
/* Get kernel function. */
|
||||
if (task.integrator_branched) {
|
||||
cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_branched_path_trace"));
|
||||
if (rtile.task == RenderTile::BAKE) {
|
||||
cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_bake"));
|
||||
}
|
||||
else if (task.integrator_branched) {
|
||||
cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_branched_path_trace"));
|
||||
}
|
||||
else {
|
||||
cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"));
|
||||
cuda_assert(cuModuleGetFunction(&cuRender, cuModule, "kernel_cuda_path_trace"));
|
||||
}
|
||||
|
||||
if (have_error()) {
|
||||
return;
|
||||
}
|
||||
|
||||
cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1));
|
||||
cuda_assert(cuFuncSetCacheConfig(cuRender, CU_FUNC_CACHE_PREFER_L1));
|
||||
|
||||
/* Allocate work tile. */
|
||||
work_tiles.alloc(1);
|
||||
@@ -1822,8 +1826,8 @@ void CUDADevice::path_trace(DeviceTask &task,
|
||||
* remain conservative for GPUs connected to a display to avoid driver
|
||||
* timeouts and display freezing. */
|
||||
int min_blocks, num_threads_per_block;
|
||||
cuda_assert(cuOccupancyMaxPotentialBlockSize(
|
||||
&min_blocks, &num_threads_per_block, cuPathTrace, NULL, 0, 0));
|
||||
cuda_assert(
|
||||
cuOccupancyMaxPotentialBlockSize(&min_blocks, &num_threads_per_block, cuRender, NULL, 0, 0));
|
||||
if (!info.display_device) {
|
||||
min_blocks *= 8;
|
||||
}
|
||||
@@ -1851,7 +1855,7 @@ void CUDADevice::path_trace(DeviceTask &task,
|
||||
void *args[] = {&d_work_tiles, &total_work_size};
|
||||
|
||||
cuda_assert(
|
||||
cuLaunchKernel(cuPathTrace, num_blocks, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
|
||||
cuLaunchKernel(cuRender, num_blocks, 1, 1, num_threads_per_block, 1, 1, 0, 0, args, 0));
|
||||
|
||||
/* Run the adaptive sampling kernels at selected samples aligned to step samples. */
|
||||
uint filter_sample = sample + wtile->num_samples - 1;
|
||||
@@ -1957,10 +1961,7 @@ void CUDADevice::shader(DeviceTask &task)
|
||||
CUdeviceptr d_output = (CUdeviceptr)task.shader_output;
|
||||
|
||||
/* get kernel function */
|
||||
if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
|
||||
cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_bake"));
|
||||
}
|
||||
else if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
|
||||
if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
|
||||
cuda_assert(cuModuleGetFunction(&cuShader, cuModule, "kernel_cuda_displace"));
|
||||
}
|
||||
else {
|
||||
@@ -2297,9 +2298,12 @@ void CUDADevice::thread_run(DeviceTask *task)
|
||||
split_kernel->path_trace(task, tile, void_buffer, void_buffer);
|
||||
}
|
||||
else {
|
||||
path_trace(*task, tile, work_tiles);
|
||||
render(*task, tile, work_tiles);
|
||||
}
|
||||
}
|
||||
else if (tile.task == RenderTile::BAKE) {
|
||||
render(*task, tile, work_tiles);
|
||||
}
|
||||
else if (tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
|
@@ -188,6 +188,7 @@ class CPUDevice : public Device {
|
||||
convert_to_byte_kernel;
|
||||
KernelFunctions<void (*)(KernelGlobals *, uint4 *, float4 *, int, int, int, int, int)>
|
||||
shader_kernel;
|
||||
KernelFunctions<void (*)(KernelGlobals *, float *, int, int, int, int, int)> bake_kernel;
|
||||
|
||||
KernelFunctions<void (*)(
|
||||
int, TileInfo *, int, int, float *, float *, float *, float *, float *, int *, int, int)>
|
||||
@@ -270,6 +271,7 @@ class CPUDevice : public Device {
|
||||
REGISTER_KERNEL(convert_to_half_float),
|
||||
REGISTER_KERNEL(convert_to_byte),
|
||||
REGISTER_KERNEL(shader),
|
||||
REGISTER_KERNEL(bake),
|
||||
REGISTER_KERNEL(filter_divide_shadow),
|
||||
REGISTER_KERNEL(filter_get_feature),
|
||||
REGISTER_KERNEL(filter_write_feature),
|
||||
@@ -895,7 +897,7 @@ class CPUDevice : public Device {
|
||||
}
|
||||
}
|
||||
|
||||
void path_trace(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
|
||||
void render(DeviceTask &task, RenderTile &tile, KernelGlobals *kg)
|
||||
{
|
||||
const bool use_coverage = kernel_data.film.cryptomatte_passes & CRYPT_ACCURATE;
|
||||
|
||||
@@ -919,12 +921,21 @@ class CPUDevice : public Device {
|
||||
break;
|
||||
}
|
||||
|
||||
for (int y = tile.y; y < tile.y + tile.h; y++) {
|
||||
for (int x = tile.x; x < tile.x + tile.w; x++) {
|
||||
if (use_coverage) {
|
||||
coverage.init_pixel(x, y);
|
||||
if (tile.task == RenderTile::PATH_TRACE) {
|
||||
for (int y = tile.y; y < tile.y + tile.h; y++) {
|
||||
for (int x = tile.x; x < tile.x + tile.w; x++) {
|
||||
if (use_coverage) {
|
||||
coverage.init_pixel(x, y);
|
||||
}
|
||||
path_trace_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y = tile.y; y < tile.y + tile.h; y++) {
|
||||
for (int x = tile.x; x < tile.x + tile.w; x++) {
|
||||
bake_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
|
||||
}
|
||||
path_trace_kernel()(kg, render_buffer, sample, x, y, tile.offset, tile.stride);
|
||||
}
|
||||
}
|
||||
tile.sample = sample + 1;
|
||||
@@ -1019,9 +1030,12 @@ class CPUDevice : public Device {
|
||||
split_kernel->path_trace(&task, tile, kgbuffer, void_buffer);
|
||||
}
|
||||
else {
|
||||
path_trace(task, tile, kg);
|
||||
render(task, tile, kg);
|
||||
}
|
||||
}
|
||||
else if (tile.task == RenderTile::BAKE) {
|
||||
render(task, tile, kg);
|
||||
}
|
||||
else if (tile.task == RenderTile::DENOISE) {
|
||||
denoise(denoising, tile);
|
||||
task.update_progress(&tile, tile.w * tile.h);
|
||||
|
@@ -451,6 +451,7 @@ class OpenCLDevice : public Device {
|
||||
device_ptr rgba_half);
|
||||
void shader(DeviceTask &task);
|
||||
void update_adaptive(DeviceTask &task, RenderTile &tile, int sample);
|
||||
void bake(DeviceTask &task, RenderTile &tile);
|
||||
|
||||
void denoise(RenderTile &tile, DenoisingTask &denoising);
|
||||
|
||||
|
@@ -1367,6 +1367,9 @@ void OpenCLDevice::thread_run(DeviceTask *task)
|
||||
*/
|
||||
clFinish(cqCommandQueue);
|
||||
}
|
||||
else if (tile.task == RenderTile::BAKE) {
|
||||
bake(*task, tile);
|
||||
}
|
||||
else if (tile.task == RenderTile::DENOISE) {
|
||||
tile.sample = tile.start_sample + tile.num_samples;
|
||||
denoise(tile, denoising);
|
||||
@@ -1858,10 +1861,7 @@ void OpenCLDevice::shader(DeviceTask &task)
|
||||
cl_int d_offset = task.offset;
|
||||
|
||||
OpenCLDevice::OpenCLProgram *program = &background_program;
|
||||
if (task.shader_eval_type >= SHADER_EVAL_BAKE) {
|
||||
program = &bake_program;
|
||||
}
|
||||
else if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
|
||||
if (task.shader_eval_type == SHADER_EVAL_DISPLACE) {
|
||||
program = &displace_program;
|
||||
}
|
||||
program->wait_for_availability();
|
||||
@@ -1892,6 +1892,51 @@ void OpenCLDevice::shader(DeviceTask &task)
|
||||
}
|
||||
}
|
||||
|
||||
void OpenCLDevice::bake(DeviceTask &task, RenderTile &rtile)
|
||||
{
|
||||
scoped_timer timer(&rtile.buffers->render_time);
|
||||
|
||||
/* Cast arguments to cl types. */
|
||||
cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
|
||||
cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
|
||||
cl_int d_x = rtile.x;
|
||||
cl_int d_y = rtile.y;
|
||||
cl_int d_w = rtile.w;
|
||||
cl_int d_h = rtile.h;
|
||||
cl_int d_offset = rtile.offset;
|
||||
cl_int d_stride = rtile.stride;
|
||||
|
||||
bake_program.wait_for_availability();
|
||||
cl_kernel kernel = bake_program();
|
||||
|
||||
cl_uint start_arg_index = kernel_set_args(kernel, 0, d_data, d_buffer);
|
||||
|
||||
set_kernel_arg_buffers(kernel, &start_arg_index);
|
||||
|
||||
start_arg_index += kernel_set_args(
|
||||
kernel, start_arg_index, d_x, d_y, d_w, d_h, d_offset, d_stride);
|
||||
|
||||
int start_sample = rtile.start_sample;
|
||||
int end_sample = rtile.start_sample + rtile.num_samples;
|
||||
|
||||
for (int sample = start_sample; sample < end_sample; sample++) {
|
||||
if (task.get_cancel()) {
|
||||
if (task.need_finish_queue == false)
|
||||
break;
|
||||
}
|
||||
|
||||
kernel_set_args(kernel, start_arg_index, sample);
|
||||
|
||||
enqueue_kernel(kernel, d_w, d_h);
|
||||
|
||||
rtile.sample = sample + 1;
|
||||
|
||||
task.update_progress(&rtile, rtile.w * rtile.h);
|
||||
}
|
||||
|
||||
clFinish(cqCommandQueue);
|
||||
}
|
||||
|
||||
string OpenCLDevice::kernel_build_options(const string *debug_src)
|
||||
{
|
||||
string build_options = "-cl-no-signed-zeros -cl-mad-enable ";
|
||||
|
@@ -229,8 +229,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
label = bsdf_microfacet_ggx_sample(kg,
|
||||
sc,
|
||||
@@ -281,7 +279,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
|
||||
&sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
label = bsdf_microfacet_beckmann_sample(kg,
|
||||
sc,
|
||||
@@ -298,7 +295,6 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
|
||||
pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
|
||||
label = bsdf_ashikhmin_shirley_sample(sc,
|
||||
sd->Ng,
|
||||
sd->I,
|
||||
@@ -504,8 +500,6 @@ ccl_device_inline
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
@@ -519,12 +513,10 @@ ccl_device_inline
|
||||
sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
|
||||
eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
@@ -595,8 +587,6 @@ ccl_device_inline
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
@@ -610,12 +600,10 @@ ccl_device_inline
|
||||
sc, sd->I, omega_in, pdf, &sd->lcg_state);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
|
||||
eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
@@ -679,18 +667,14 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
bsdf_microfacet_ggx_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
bsdf_microfacet_beckmann_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
|
||||
bsdf_ashikhmin_shirley_blur(sc, roughness);
|
||||
break;
|
||||
case CLOSURE_BSDF_HAIR_PRINCIPLED_ID:
|
||||
@@ -719,18 +703,14 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
|
||||
return bsdf_microfacet_merge(a, b);
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
|
||||
return bsdf_ashikhmin_velvet_merge(a, b);
|
||||
|
@@ -32,20 +32,11 @@ Other than that, the implementation directly follows the paper.
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device int bsdf_ashikhmin_shirley_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_ashikhmin_shirley_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
|
||||
bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID;
|
||||
bsdf->type = CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
|
@@ -256,9 +256,7 @@ ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float
|
||||
{
|
||||
float3 F = make_float3(1.0f, 1.0f, 1.0f);
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
|
||||
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
|
||||
if (use_fresnel) {
|
||||
float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
|
||||
|
||||
@@ -311,19 +309,27 @@ ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
|
||||
bsdf->extra = NULL;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
/* Required to maintain OSL interface. */
|
||||
ccl_device int bsdf_microfacet_ggx_isotropic_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
return bsdf_microfacet_ggx_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
|
||||
|
||||
@@ -361,32 +367,6 @@ ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosur
|
||||
(bsdf_a->extra->clearcoat == bsdf_b->extra->clearcoat)));
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra = NULL;
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
|
||||
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
|
||||
|
||||
bsdf_microfacet_fresnel_color(sd, bsdf);
|
||||
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->extra = NULL;
|
||||
@@ -636,8 +616,7 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg,
|
||||
*eval = make_float3(1e6f, 1e6f, 1e6f);
|
||||
|
||||
bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID ||
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID ||
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
|
||||
bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
|
||||
|
||||
/* if fresnel is used, calculate the color with reflection_color(...) */
|
||||
if (use_fresnel) {
|
||||
@@ -811,19 +790,18 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg,
|
||||
ccl_device int bsdf_microfacet_beckmann_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_beckmann_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
/* Required to maintain OSL interface. */
|
||||
ccl_device int bsdf_microfacet_beckmann_isotropic_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_x = saturate(bsdf->alpha_x);
|
||||
bsdf->alpha_y = saturate(bsdf->alpha_y);
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID;
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL;
|
||||
return bsdf_microfacet_beckmann_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_beckmann_refraction_setup(MicrofacetBsdf *bsdf)
|
||||
|
@@ -384,32 +384,10 @@ ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
|
||||
return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG;
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
if (is_zero(bsdf->T))
|
||||
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf,
|
||||
const ShaderData *sd)
|
||||
{
|
||||
if (is_zero(bsdf->T))
|
||||
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
|
||||
|
||||
bsdf_microfacet_fresnel_color(sd, bsdf);
|
||||
|
||||
return bsdf_microfacet_multi_ggx_common_setup(bsdf);
|
||||
}
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
|
||||
{
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
if (is_zero(bsdf->T))
|
||||
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
|
||||
|
||||
@@ -418,7 +396,8 @@ ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
|
||||
|
||||
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
|
||||
{
|
||||
bsdf->alpha_y = bsdf->alpha_x;
|
||||
if (is_zero(bsdf->T))
|
||||
bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
|
||||
|
||||
bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
|
||||
|
||||
|
@@ -18,19 +18,33 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef __BAKING__
|
||||
|
||||
ccl_device_inline void compute_light_pass(
|
||||
ccl_device_noinline void compute_light_pass(
|
||||
KernelGlobals *kg, ShaderData *sd, PathRadiance *L, uint rng_hash, int pass_filter, int sample)
|
||||
{
|
||||
kernel_assert(kernel_data.film.use_light_pass);
|
||||
|
||||
PathRadiance L_sample;
|
||||
PathState state;
|
||||
Ray ray;
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
/* emission and indirect shader data memory used by various functions */
|
||||
ShaderData emission_sd, indirect_sd;
|
||||
/* Emission and indirect shader data memory used by various functions. */
|
||||
ShaderDataTinyStorage emission_sd_storage;
|
||||
ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
|
||||
ShaderData indirect_sd;
|
||||
|
||||
/* Init radiance. */
|
||||
path_radiance_init(kg, L);
|
||||
|
||||
/* Init path state. */
|
||||
PathState state;
|
||||
path_state_init(kg, emission_sd, &state, rng_hash, sample, NULL);
|
||||
|
||||
/* Evaluate surface shader. */
|
||||
shader_eval_surface(kg, sd, &state, NULL, state.flag);
|
||||
|
||||
/* TODO, disable more closures we don't need besides transparent */
|
||||
shader_bsdf_disable_transparency(kg, sd);
|
||||
|
||||
/* Init ray. */
|
||||
Ray ray;
|
||||
ray.P = sd->P + sd->Ng;
|
||||
ray.D = -sd->Ng;
|
||||
ray.t = FLT_MAX;
|
||||
@@ -38,18 +52,6 @@ ccl_device_inline void compute_light_pass(
|
||||
ray.time = 0.5f;
|
||||
# endif
|
||||
|
||||
/* init radiance */
|
||||
path_radiance_init(kg, &L_sample);
|
||||
|
||||
/* init path state */
|
||||
path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
|
||||
|
||||
/* evaluate surface shader */
|
||||
shader_eval_surface(kg, sd, &state, NULL, state.flag);
|
||||
|
||||
/* TODO, disable more closures we don't need besides transparent */
|
||||
shader_bsdf_disable_transparency(kg, sd);
|
||||
|
||||
# ifdef __BRANCHED_PATH__
|
||||
if (!kernel_data.integrator.branched) {
|
||||
/* regular path tracer */
|
||||
@@ -57,14 +59,13 @@ ccl_device_inline void compute_light_pass(
|
||||
|
||||
/* sample ambient occlusion */
|
||||
if (pass_filter & BAKE_FILTER_AO) {
|
||||
kernel_path_ao(
|
||||
kg, sd, &emission_sd, &L_sample, &state, throughput, shader_bsdf_alpha(kg, sd));
|
||||
kernel_path_ao(kg, sd, emission_sd, L, &state, throughput, shader_bsdf_alpha(kg, sd));
|
||||
}
|
||||
|
||||
/* sample emission */
|
||||
if ((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
|
||||
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
|
||||
path_radiance_accum_emission(kg, &L_sample, &state, throughput, emission);
|
||||
path_radiance_accum_emission(kg, L, &state, throughput, emission);
|
||||
}
|
||||
|
||||
bool is_sss_sample = false;
|
||||
@@ -77,12 +78,10 @@ ccl_device_inline void compute_light_pass(
|
||||
SubsurfaceIndirectRays ss_indirect;
|
||||
kernel_path_subsurface_init_indirect(&ss_indirect);
|
||||
if (kernel_path_subsurface_scatter(
|
||||
kg, sd, &emission_sd, &L_sample, &state, &ray, &throughput, &ss_indirect)) {
|
||||
kg, sd, emission_sd, L, &state, &ray, &throughput, &ss_indirect)) {
|
||||
while (ss_indirect.num_rays) {
|
||||
kernel_path_subsurface_setup_indirect(
|
||||
kg, &ss_indirect, &state, &ray, &L_sample, &throughput);
|
||||
kernel_path_indirect(
|
||||
kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
|
||||
kernel_path_subsurface_setup_indirect(kg, &ss_indirect, &state, &ray, L, &throughput);
|
||||
kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
|
||||
}
|
||||
is_sss_sample = true;
|
||||
}
|
||||
@@ -91,18 +90,18 @@ ccl_device_inline void compute_light_pass(
|
||||
|
||||
/* sample light and BSDF */
|
||||
if (!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
|
||||
kernel_path_surface_connect_light(kg, sd, &emission_sd, throughput, &state, &L_sample);
|
||||
kernel_path_surface_connect_light(kg, sd, emission_sd, throughput, &state, L);
|
||||
|
||||
if (kernel_path_surface_bounce(kg, sd, &throughput, &state, &L_sample.state, &ray)) {
|
||||
if (kernel_path_surface_bounce(kg, sd, &throughput, &state, &L->state, &ray)) {
|
||||
# ifdef __LAMP_MIS__
|
||||
state.ray_t = 0.0f;
|
||||
# endif
|
||||
/* compute indirect light */
|
||||
kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
|
||||
kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
|
||||
|
||||
/* sum and reset indirect light pass variables for the next samples */
|
||||
path_radiance_sum_indirect(&L_sample);
|
||||
path_radiance_reset_indirect(&L_sample);
|
||||
path_radiance_sum_indirect(L);
|
||||
path_radiance_reset_indirect(L);
|
||||
}
|
||||
}
|
||||
# ifdef __BRANCHED_PATH__
|
||||
@@ -112,13 +111,13 @@ ccl_device_inline void compute_light_pass(
|
||||
|
||||
/* sample ambient occlusion */
|
||||
if (pass_filter & BAKE_FILTER_AO) {
|
||||
kernel_branched_path_ao(kg, sd, &emission_sd, &L_sample, &state, throughput);
|
||||
kernel_branched_path_ao(kg, sd, emission_sd, L, &state, throughput);
|
||||
}
|
||||
|
||||
/* sample emission */
|
||||
if ((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
|
||||
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
|
||||
path_radiance_accum_emission(kg, &L_sample, &state, throughput, emission);
|
||||
path_radiance_accum_emission(kg, L, &state, throughput, emission);
|
||||
}
|
||||
|
||||
# ifdef __SUBSURFACE__
|
||||
@@ -127,7 +126,7 @@ ccl_device_inline void compute_light_pass(
|
||||
/* When mixing BSSRDF and BSDF closures we should skip BSDF lighting
|
||||
* if scattering was successful. */
|
||||
kernel_branched_path_subsurface_scatter(
|
||||
kg, sd, &indirect_sd, &emission_sd, &L_sample, &state, &ray, throughput);
|
||||
kg, sd, &indirect_sd, emission_sd, L, &state, &ray, throughput);
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -138,19 +137,16 @@ ccl_device_inline void compute_light_pass(
|
||||
if (kernel_data.integrator.use_direct_light) {
|
||||
int all = kernel_data.integrator.sample_all_lights_direct;
|
||||
kernel_branched_path_surface_connect_light(
|
||||
kg, sd, &emission_sd, &state, throughput, 1.0f, &L_sample, all);
|
||||
kg, sd, emission_sd, &state, throughput, 1.0f, L, all);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* indirect light */
|
||||
kernel_branched_path_surface_indirect_light(
|
||||
kg, sd, &indirect_sd, &emission_sd, throughput, 1.0f, &state, &L_sample);
|
||||
kg, sd, &indirect_sd, emission_sd, throughput, 1.0f, &state, L);
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
/* accumulate into master L */
|
||||
path_radiance_accum_sample(L, &L_sample);
|
||||
}
|
||||
|
||||
/* this helps with AA but it's not the real solution as it does not AA the geometry
|
||||
@@ -225,41 +221,28 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
|
||||
return out;
|
||||
}
|
||||
|
||||
ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
|
||||
ccl_global uint4 *input,
|
||||
ccl_global float4 *output,
|
||||
ShaderEvalType type,
|
||||
int pass_filter,
|
||||
int i,
|
||||
int offset,
|
||||
int sample)
|
||||
ccl_device void kernel_bake_evaluate(
|
||||
KernelGlobals *kg, ccl_global float *buffer, int sample, int x, int y, int offset, int stride)
|
||||
{
|
||||
ShaderData sd;
|
||||
PathState state = {0};
|
||||
uint4 in = input[i * 2];
|
||||
uint4 diff = input[i * 2 + 1];
|
||||
/* Setup render buffers. */
|
||||
const int index = offset + x + y * stride;
|
||||
const int pass_stride = kernel_data.film.pass_stride;
|
||||
buffer += index * pass_stride;
|
||||
|
||||
float3 out = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
int object = in.x;
|
||||
int prim = in.y;
|
||||
ccl_global float *primitive = buffer + kernel_data.film.pass_bake_primitive;
|
||||
ccl_global float *differential = buffer + kernel_data.film.pass_bake_differential;
|
||||
ccl_global float *output = buffer + kernel_data.film.pass_combined;
|
||||
|
||||
int prim = __float_as_uint(primitive[1]);
|
||||
if (prim == -1)
|
||||
return;
|
||||
|
||||
float u = __uint_as_float(in.z);
|
||||
float v = __uint_as_float(in.w);
|
||||
|
||||
float dudx = __uint_as_float(diff.x);
|
||||
float dudy = __uint_as_float(diff.y);
|
||||
float dvdx = __uint_as_float(diff.z);
|
||||
float dvdy = __uint_as_float(diff.w);
|
||||
prim += kernel_data.bake.tri_offset;
|
||||
|
||||
/* Random number generator. */
|
||||
uint rng_hash = hash_uint2(x, y) ^ kernel_data.integrator.seed;
|
||||
int num_samples = kernel_data.integrator.aa_samples;
|
||||
|
||||
/* random number generator */
|
||||
uint rng_hash = cmj_hash(offset + i, kernel_data.integrator.seed);
|
||||
|
||||
float filter_x, filter_y;
|
||||
if (sample == 0) {
|
||||
filter_x = filter_y = 0.5f;
|
||||
@@ -268,23 +251,29 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
|
||||
path_rng_2D(kg, rng_hash, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y);
|
||||
}
|
||||
|
||||
/* subpixel u/v offset */
|
||||
/* Barycentric UV with subpixel offset. */
|
||||
float u = primitive[2];
|
||||
float v = primitive[3];
|
||||
|
||||
float dudx = differential[0];
|
||||
float dudy = differential[1];
|
||||
float dvdx = differential[2];
|
||||
float dvdy = differential[3];
|
||||
|
||||
if (sample > 0) {
|
||||
u = bake_clamp_mirror_repeat(u + dudx * (filter_x - 0.5f) + dudy * (filter_y - 0.5f), 1.0f);
|
||||
v = bake_clamp_mirror_repeat(v + dvdx * (filter_x - 0.5f) + dvdy * (filter_y - 0.5f),
|
||||
1.0f - u);
|
||||
}
|
||||
|
||||
/* triangle */
|
||||
/* Shader data setup. */
|
||||
int object = kernel_data.bake.object_index;
|
||||
int shader;
|
||||
float3 P, Ng;
|
||||
|
||||
triangle_point_normal(kg, object, prim, u, v, &P, &Ng, &shader);
|
||||
|
||||
/* light passes */
|
||||
PathRadiance L;
|
||||
path_radiance_init(kg, &L);
|
||||
|
||||
ShaderData sd;
|
||||
shader_setup_from_sample(
|
||||
kg,
|
||||
&sd,
|
||||
@@ -302,7 +291,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
|
||||
LAMP_NONE);
|
||||
sd.I = sd.N;
|
||||
|
||||
/* update differentials */
|
||||
/* Setup differentials. */
|
||||
sd.dP.dx = sd.dPdu * dudx + sd.dPdv * dvdx;
|
||||
sd.dP.dy = sd.dPdu * dudy + sd.dPdv * dvdy;
|
||||
sd.du.dx = dudx;
|
||||
@@ -310,17 +299,24 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
|
||||
sd.dv.dx = dvdx;
|
||||
sd.dv.dy = dvdy;
|
||||
|
||||
/* set RNG state for shaders that use sampling */
|
||||
/* Set RNG state for shaders that use sampling. */
|
||||
PathState state = {0};
|
||||
state.rng_hash = rng_hash;
|
||||
state.rng_offset = 0;
|
||||
state.sample = sample;
|
||||
state.num_samples = num_samples;
|
||||
state.min_ray_pdf = FLT_MAX;
|
||||
|
||||
/* light passes if we need more than color */
|
||||
if (pass_filter & ~BAKE_FILTER_COLOR)
|
||||
/* Light passes if we need more than color. */
|
||||
PathRadiance L;
|
||||
int pass_filter = kernel_data.bake.pass_filter;
|
||||
|
||||
if (kernel_data.bake.pass_filter & ~BAKE_FILTER_COLOR)
|
||||
compute_light_pass(kg, &sd, &L, rng_hash, pass_filter, sample);
|
||||
|
||||
float3 out = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
ShaderEvalType type = (ShaderEvalType)kernel_data.bake.type;
|
||||
switch (type) {
|
||||
/* data passes */
|
||||
case SHADER_EVAL_NORMAL:
|
||||
@@ -441,10 +437,8 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg,
|
||||
}
|
||||
|
||||
/* write output */
|
||||
const float output_fac = 1.0f / num_samples;
|
||||
const float4 scaled_result = make_float4(out.x, out.y, out.z, 1.0f) * output_fac;
|
||||
|
||||
output[i] = (sample == 0) ? scaled_result : output[i] + scaled_result;
|
||||
const float4 result = make_float4(out.x, out.y, out.z, 1.0f);
|
||||
kernel_write_pass_float4(output, result);
|
||||
}
|
||||
|
||||
#endif /* __BAKING__ */
|
||||
|
@@ -28,13 +28,13 @@ ccl_device float4 film_get_pass_result(KernelGlobals *kg,
|
||||
int display_pass_components = kernel_data.film.display_pass_components;
|
||||
|
||||
if (display_pass_components == 4) {
|
||||
ccl_global float4 *in = (ccl_global float4 *)(buffer + display_pass_stride +
|
||||
index * kernel_data.film.pass_stride);
|
||||
float4 in = *(ccl_global float4 *)(buffer + display_pass_stride +
|
||||
index * kernel_data.film.pass_stride);
|
||||
float alpha = use_display_sample_scale ?
|
||||
(kernel_data.film.use_display_pass_alpha ? in->w : 1.0f / sample_scale) :
|
||||
(kernel_data.film.use_display_pass_alpha ? in.w : 1.0f / sample_scale) :
|
||||
1.0f;
|
||||
|
||||
pass_result = make_float4(in->x, in->y, in->z, alpha);
|
||||
pass_result = make_float4(in.x, in.y, in.z, alpha);
|
||||
|
||||
int display_divide_pass_stride = kernel_data.film.display_divide_pass_stride;
|
||||
if (display_divide_pass_stride != -1) {
|
||||
|
@@ -1041,11 +1041,19 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg,
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* compute random point in triangle */
|
||||
randu = sqrtf(randu);
|
||||
/* compute random point in triangle. From Eric Heitz's "A Low-Distortion Map Between Triangle
|
||||
* and Square" */
|
||||
float u = randu;
|
||||
float v = randv;
|
||||
if (v > u) {
|
||||
u *= 0.5f;
|
||||
v -= u;
|
||||
}
|
||||
else {
|
||||
v *= 0.5f;
|
||||
u -= v;
|
||||
}
|
||||
|
||||
const float u = 1.0f - randu;
|
||||
const float v = randv * randu;
|
||||
const float t = 1.0f - u - v;
|
||||
ls->P = u * V[0] + v * V[1] + t * V[2];
|
||||
/* compute incoming direction, distance and pdf */
|
||||
|
@@ -395,6 +395,10 @@ typedef enum PassType {
|
||||
PASS_VOLUME_INDIRECT,
|
||||
/* No Scatter color since it's tricky to define what it would even mean. */
|
||||
PASS_CATEGORY_LIGHT_END = 63,
|
||||
|
||||
PASS_BAKE_PRIMITIVE,
|
||||
PASS_BAKE_DIFFERENTIAL,
|
||||
PASS_CATEGORY_BAKE_END = 95
|
||||
} PassType;
|
||||
|
||||
#define PASS_ANY (~0)
|
||||
@@ -1248,6 +1252,10 @@ typedef struct KernelFilm {
|
||||
float4 xyz_to_b;
|
||||
float4 rgb_to_y;
|
||||
|
||||
int pass_bake_primitive;
|
||||
int pass_bake_differential;
|
||||
int pad;
|
||||
|
||||
#ifdef __KERNEL_DEBUG__
|
||||
int pass_bvh_traversed_nodes;
|
||||
int pass_bvh_traversed_instances;
|
||||
@@ -1427,6 +1435,14 @@ typedef struct KernelTables {
|
||||
} KernelTables;
|
||||
static_assert_align(KernelTables, 16);
|
||||
|
||||
typedef struct KernelBake {
|
||||
int object_index;
|
||||
int tri_offset;
|
||||
int type;
|
||||
int pass_filter;
|
||||
} KernelBake;
|
||||
static_assert_align(KernelBake, 16);
|
||||
|
||||
typedef struct KernelData {
|
||||
KernelCamera cam;
|
||||
KernelFilm film;
|
||||
@@ -1435,6 +1451,7 @@ typedef struct KernelData {
|
||||
KernelBVH bvh;
|
||||
KernelCurves curve;
|
||||
KernelTables tables;
|
||||
KernelBake bake;
|
||||
} KernelData;
|
||||
static_assert_align(KernelData, 16);
|
||||
|
||||
|
@@ -46,6 +46,9 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
|
||||
int offset,
|
||||
int sample);
|
||||
|
||||
void KERNEL_FUNCTION_FULL_NAME(bake)(
|
||||
KernelGlobals *kg, float *buffer, int sample, int x, int y, int offset, int stride);
|
||||
|
||||
/* Split kernels */
|
||||
|
||||
void KERNEL_FUNCTION_FULL_NAME(data_init)(KernelGlobals *kg,
|
||||
|
@@ -132,6 +132,18 @@ void KERNEL_FUNCTION_FULL_NAME(convert_to_half_float)(KernelGlobals *kg,
|
||||
# endif /* KERNEL_STUB */
|
||||
}
|
||||
|
||||
/* Bake */
|
||||
|
||||
void KERNEL_FUNCTION_FULL_NAME(bake)(
|
||||
KernelGlobals *kg, float *buffer, int sample, int x, int y, int offset, int stride)
|
||||
{
|
||||
# ifdef KERNEL_STUB
|
||||
STUB_ASSERT(KERNEL_ARCH, bake);
|
||||
# else
|
||||
kernel_bake_evaluate(kg, buffer, sample, x, y, offset, stride);
|
||||
# endif /* KERNEL_STUB */
|
||||
}
|
||||
|
||||
/* Shader Evaluate */
|
||||
|
||||
void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
|
||||
@@ -146,12 +158,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
|
||||
# ifdef KERNEL_STUB
|
||||
STUB_ASSERT(KERNEL_ARCH, shader);
|
||||
# else
|
||||
if (type >= SHADER_EVAL_BAKE) {
|
||||
# ifdef __BAKING__
|
||||
kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, filter, i, offset, sample);
|
||||
# endif
|
||||
}
|
||||
else if (type == SHADER_EVAL_DISPLACE) {
|
||||
if (type == SHADER_EVAL_DISPLACE) {
|
||||
kernel_displace_evaluate(kg, input, output, i);
|
||||
}
|
||||
else {
|
||||
|
@@ -214,13 +214,16 @@ kernel_cuda_background(uint4 *input,
|
||||
#ifdef __BAKING__
|
||||
extern "C" __global__ void
|
||||
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
|
||||
kernel_cuda_bake(uint4 *input, float4 *output, int type, int filter, int sx, int sw, int offset, int sample)
|
||||
kernel_cuda_bake(WorkTile *tile, uint total_work_size)
|
||||
{
|
||||
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
|
||||
int work_index = ccl_global_id(0);
|
||||
|
||||
if(work_index < total_work_size) {
|
||||
uint x, y, sample;
|
||||
get_work_pixel(tile, work_index, &x, &y, &sample);
|
||||
|
||||
if(x < sx + sw) {
|
||||
KernelGlobals kg;
|
||||
kernel_bake_evaluate(&kg, input, output, (ShaderEvalType)type, filter, x, offset, sample);
|
||||
kernel_bake_evaluate(&kg, tile->buffer, sample, x, y, tile->offset, tile->stride);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@@ -100,14 +100,14 @@ CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
|
||||
BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley,
|
||||
ashikhmin_shirley_aniso,
|
||||
ashikhmin_shirley,
|
||||
MicrofacetBsdf,
|
||||
LABEL_GLOSSY | LABEL_REFLECT)
|
||||
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T),
|
||||
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y),
|
||||
BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley_aniso)
|
||||
BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE)
|
||||
CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N),
|
||||
@@ -121,42 +121,42 @@ CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth),
|
||||
BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXIsotropic,
|
||||
microfacet_ggx_isotropic,
|
||||
MicrofacetBsdf,
|
||||
LABEL_GLOSSY | LABEL_REFLECT)
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXIsotropicClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXIsotropicClosure, params.alpha_x),
|
||||
BSDF_CLOSURE_CLASS_END(MicrofacetGGXIsotropic, microfacet_ggx_isotropic)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX,
|
||||
microfacet_ggx,
|
||||
MicrofacetBsdf,
|
||||
LABEL_GLOSSY | LABEL_REFLECT)
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.T),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_y),
|
||||
BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXAniso,
|
||||
microfacet_ggx_aniso,
|
||||
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannIsotropic,
|
||||
microfacet_beckmann_isotropic,
|
||||
MicrofacetBsdf,
|
||||
LABEL_GLOSSY | LABEL_REFLECT)
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetGGXAnisoClosure, params.T),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetGGXAnisoClosure, params.alpha_y),
|
||||
BSDF_CLOSURE_CLASS_END(MicrofacetGGXAniso, microfacet_ggx_aniso)
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannIsotropicClosure, params.N),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannIsotropicClosure, params.alpha_x),
|
||||
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannIsotropic, microfacet_beckmann_isotropic)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann,
|
||||
microfacet_beckmann,
|
||||
MicrofacetBsdf,
|
||||
LABEL_GLOSSY | LABEL_REFLECT)
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.T),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_y),
|
||||
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannAniso,
|
||||
microfacet_beckmann_aniso,
|
||||
MicrofacetBsdf,
|
||||
LABEL_GLOSSY | LABEL_REFLECT)
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.N),
|
||||
CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannAnisoClosure, params.T),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_x),
|
||||
CLOSURE_FLOAT_PARAM(MicrofacetBeckmannAnisoClosure, params.alpha_y),
|
||||
BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannAniso, microfacet_beckmann_aniso)
|
||||
|
||||
BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction,
|
||||
microfacet_ggx_refraction,
|
||||
MicrofacetBsdf,
|
||||
@@ -362,13 +362,13 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
id++,
|
||||
closure_bsdf_transparent_params(),
|
||||
closure_bsdf_transparent_prepare);
|
||||
register_closure(
|
||||
ss, "microfacet_ggx", id++, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
|
||||
register_closure(ss,
|
||||
"microfacet_ggx_aniso",
|
||||
"microfacet_ggx",
|
||||
id++,
|
||||
bsdf_microfacet_ggx_aniso_params(),
|
||||
bsdf_microfacet_ggx_aniso_prepare);
|
||||
bsdf_microfacet_ggx_isotropic_params(),
|
||||
bsdf_microfacet_ggx_isotropic_prepare);
|
||||
register_closure(
|
||||
ss, "microfacet_ggx_aniso", id++, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare);
|
||||
register_closure(ss,
|
||||
"microfacet_ggx_refraction",
|
||||
id++,
|
||||
@@ -417,13 +417,13 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
register_closure(ss,
|
||||
"microfacet_beckmann",
|
||||
id++,
|
||||
bsdf_microfacet_beckmann_params(),
|
||||
bsdf_microfacet_beckmann_prepare);
|
||||
bsdf_microfacet_beckmann_isotropic_params(),
|
||||
bsdf_microfacet_beckmann_isotropic_prepare);
|
||||
register_closure(ss,
|
||||
"microfacet_beckmann_aniso",
|
||||
id++,
|
||||
bsdf_microfacet_beckmann_aniso_params(),
|
||||
bsdf_microfacet_beckmann_aniso_prepare);
|
||||
bsdf_microfacet_beckmann_params(),
|
||||
bsdf_microfacet_beckmann_prepare);
|
||||
register_closure(ss,
|
||||
"microfacet_beckmann_refraction",
|
||||
id++,
|
||||
@@ -432,8 +432,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
|
||||
register_closure(ss,
|
||||
"ashikhmin_shirley",
|
||||
id++,
|
||||
bsdf_ashikhmin_shirley_aniso_params(),
|
||||
bsdf_ashikhmin_shirley_aniso_prepare);
|
||||
bsdf_ashikhmin_shirley_params(),
|
||||
bsdf_ashikhmin_shirley_prepare);
|
||||
register_closure(
|
||||
ss, "ashikhmin_velvet", id++, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare);
|
||||
register_closure(
|
||||
@@ -582,7 +582,7 @@ class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure {
|
||||
return;
|
||||
}
|
||||
|
||||
sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
|
||||
sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -676,7 +676,7 @@ class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure {
|
||||
}
|
||||
|
||||
bsdf->ior = 0.0f;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -801,7 +801,7 @@ class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosu
|
||||
return;
|
||||
}
|
||||
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -320,9 +320,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
|
||||
/* setup bsdf */
|
||||
if (distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID ||
|
||||
roughness <= 0.075f) /* use single-scatter GGX */
|
||||
sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf, sd);
|
||||
sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd);
|
||||
else /* use multi-scatter GGX */
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf, sd);
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd);
|
||||
}
|
||||
}
|
||||
# ifdef __CAUSTICS_TRICKS__
|
||||
@@ -515,12 +515,34 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
|
||||
float roughness = sqr(param1);
|
||||
|
||||
bsdf->N = N;
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->alpha_x = roughness;
|
||||
bsdf->alpha_y = roughness;
|
||||
bsdf->ior = 0.0f;
|
||||
bsdf->extra = NULL;
|
||||
|
||||
if (data_node.y == SVM_STACK_INVALID) {
|
||||
bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->alpha_x = roughness;
|
||||
bsdf->alpha_y = roughness;
|
||||
}
|
||||
else {
|
||||
bsdf->T = stack_load_float3(stack, data_node.y);
|
||||
|
||||
/* rotate tangent */
|
||||
float rotation = stack_load_float(stack, data_node.z);
|
||||
if (rotation != 0.0f)
|
||||
bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
|
||||
|
||||
/* compute roughness */
|
||||
float anisotropy = clamp(param2, -0.99f, 0.99f);
|
||||
if (anisotropy < 0.0f) {
|
||||
bsdf->alpha_x = roughness / (1.0f + anisotropy);
|
||||
bsdf->alpha_y = roughness * (1.0f + anisotropy);
|
||||
}
|
||||
else {
|
||||
bsdf->alpha_x = roughness * (1.0f - anisotropy);
|
||||
bsdf->alpha_y = roughness / (1.0f - anisotropy);
|
||||
}
|
||||
}
|
||||
|
||||
/* setup bsdf */
|
||||
if (type == CLOSURE_BSDF_REFLECTION_ID)
|
||||
sd->flag |= bsdf_reflection_setup(bsdf);
|
||||
@@ -529,10 +551,10 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
|
||||
else if (type == CLOSURE_BSDF_MICROFACET_GGX_ID)
|
||||
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
|
||||
else if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
|
||||
kernel_assert(stack_valid(data_node.z));
|
||||
kernel_assert(stack_valid(data_node.w));
|
||||
bsdf->extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
if (bsdf->extra) {
|
||||
bsdf->extra->color = stack_load_float3(stack, data_node.z);
|
||||
bsdf->extra->color = stack_load_float3(stack, data_node.w);
|
||||
bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
|
||||
@@ -675,64 +697,6 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg,
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID:
|
||||
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID: {
|
||||
#ifdef __CAUSTICS_TRICKS__
|
||||
if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
|
||||
break;
|
||||
#endif
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
|
||||
|
||||
if (bsdf) {
|
||||
bsdf->N = N;
|
||||
bsdf->extra = NULL;
|
||||
bsdf->T = stack_load_float3(stack, data_node.y);
|
||||
|
||||
/* rotate tangent */
|
||||
float rotation = stack_load_float(stack, data_node.z);
|
||||
|
||||
if (rotation != 0.0f)
|
||||
bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
|
||||
|
||||
/* compute roughness */
|
||||
float roughness = sqr(param1);
|
||||
float anisotropy = clamp(param2, -0.99f, 0.99f);
|
||||
|
||||
if (anisotropy < 0.0f) {
|
||||
bsdf->alpha_x = roughness / (1.0f + anisotropy);
|
||||
bsdf->alpha_y = roughness * (1.0f + anisotropy);
|
||||
}
|
||||
else {
|
||||
bsdf->alpha_x = roughness * (1.0f - anisotropy);
|
||||
bsdf->alpha_y = roughness / (1.0f - anisotropy);
|
||||
}
|
||||
|
||||
bsdf->ior = 0.0f;
|
||||
|
||||
if (type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
|
||||
sd->flag |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
|
||||
}
|
||||
else if (type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
|
||||
sd->flag |= bsdf_microfacet_ggx_aniso_setup(bsdf);
|
||||
}
|
||||
else if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
|
||||
kernel_assert(stack_valid(data_node.w));
|
||||
bsdf->extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
|
||||
if (bsdf->extra) {
|
||||
bsdf->extra->color = stack_load_float3(stack, data_node.w);
|
||||
bsdf->extra->cspec0 = make_float3(0.0f, 0.0f, 0.0f);
|
||||
bsdf->extra->clearcoat = 0.0f;
|
||||
sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
|
||||
}
|
||||
}
|
||||
else
|
||||
sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
|
||||
float3 weight = sd->svm_closure_weight * mix_weight;
|
||||
VelvetBsdf *bsdf = (VelvetBsdf *)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
|
||||
|
@@ -539,12 +539,6 @@ typedef enum ClosureType {
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
|
||||
CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
|
||||
CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_FRESNEL_ID,
|
||||
CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
|
||||
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
|
||||
CLOSURE_BSDF_PHONG_RAMP_ID,
|
||||
CLOSURE_BSDF_GLOSSY_TOON_ID,
|
||||
@@ -605,10 +599,9 @@ typedef enum ClosureType {
|
||||
#define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID)
|
||||
#define CLOSURE_IS_BSDF_MULTISCATTER(type) \
|
||||
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID || \
|
||||
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
|
||||
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)
|
||||
#define CLOSURE_IS_BSDF_MICROFACET(type) \
|
||||
((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID) || \
|
||||
((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \
|
||||
(type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \
|
||||
type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \
|
||||
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID))
|
||||
@@ -616,8 +609,7 @@ typedef enum ClosureType {
|
||||
(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \
|
||||
type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \
|
||||
type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \
|
||||
type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID || \
|
||||
type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID)
|
||||
type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID)
|
||||
#define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
|
||||
#define CLOSURE_IS_BSSRDF(type) \
|
||||
(type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "render/bake.h"
|
||||
#include "render/buffers.h"
|
||||
#include "render/integrator.h"
|
||||
#include "render/mesh.h"
|
||||
#include "render/object.h"
|
||||
@@ -24,235 +25,13 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
BakeData::BakeData(const int object, const size_t tri_offset, const size_t num_pixels)
|
||||
: m_object(object), m_tri_offset(tri_offset), m_num_pixels(num_pixels)
|
||||
{
|
||||
m_primitive.resize(num_pixels);
|
||||
m_u.resize(num_pixels);
|
||||
m_v.resize(num_pixels);
|
||||
m_dudx.resize(num_pixels);
|
||||
m_dudy.resize(num_pixels);
|
||||
m_dvdx.resize(num_pixels);
|
||||
m_dvdy.resize(num_pixels);
|
||||
}
|
||||
|
||||
BakeData::~BakeData()
|
||||
{
|
||||
m_primitive.clear();
|
||||
m_u.clear();
|
||||
m_v.clear();
|
||||
m_dudx.clear();
|
||||
m_dudy.clear();
|
||||
m_dvdx.clear();
|
||||
m_dvdy.clear();
|
||||
}
|
||||
|
||||
void BakeData::set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy)
|
||||
{
|
||||
m_primitive[i] = (prim == -1 ? -1 : m_tri_offset + prim);
|
||||
m_u[i] = uv[0];
|
||||
m_v[i] = uv[1];
|
||||
m_dudx[i] = dudx;
|
||||
m_dudy[i] = dudy;
|
||||
m_dvdx[i] = dvdx;
|
||||
m_dvdy[i] = dvdy;
|
||||
}
|
||||
|
||||
void BakeData::set_null(int i)
|
||||
{
|
||||
m_primitive[i] = -1;
|
||||
}
|
||||
|
||||
int BakeData::object()
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
size_t BakeData::size()
|
||||
{
|
||||
return m_num_pixels;
|
||||
}
|
||||
|
||||
bool BakeData::is_valid(int i)
|
||||
{
|
||||
return m_primitive[i] != -1;
|
||||
}
|
||||
|
||||
uint4 BakeData::data(int i)
|
||||
{
|
||||
return make_uint4(m_object, m_primitive[i], __float_as_int(m_u[i]), __float_as_int(m_v[i]));
|
||||
}
|
||||
|
||||
uint4 BakeData::differentials(int i)
|
||||
{
|
||||
return make_uint4(__float_as_int(m_dudx[i]),
|
||||
__float_as_int(m_dudy[i]),
|
||||
__float_as_int(m_dvdx[i]),
|
||||
__float_as_int(m_dvdy[i]));
|
||||
}
|
||||
|
||||
BakeManager::BakeManager()
|
||||
{
|
||||
m_bake_data = NULL;
|
||||
m_is_baking = false;
|
||||
need_update = true;
|
||||
m_shader_limit = 512 * 512;
|
||||
}
|
||||
|
||||
BakeManager::~BakeManager()
|
||||
{
|
||||
if (m_bake_data)
|
||||
delete m_bake_data;
|
||||
}
|
||||
|
||||
bool BakeManager::get_baking()
|
||||
{
|
||||
return m_is_baking;
|
||||
}
|
||||
|
||||
void BakeManager::set_baking(const bool value)
|
||||
{
|
||||
m_is_baking = value;
|
||||
}
|
||||
|
||||
BakeData *BakeManager::init(const int object, const size_t tri_offset, const size_t num_pixels)
|
||||
{
|
||||
m_bake_data = new BakeData(object, tri_offset, num_pixels);
|
||||
return m_bake_data;
|
||||
}
|
||||
|
||||
void BakeManager::set_shader_limit(const size_t x, const size_t y)
|
||||
{
|
||||
m_shader_limit = x * y;
|
||||
m_shader_limit = (size_t)pow(2, std::ceil(log(m_shader_limit) / log(2)));
|
||||
}
|
||||
|
||||
bool BakeManager::bake(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress,
|
||||
ShaderEvalType shader_type,
|
||||
const int pass_filter,
|
||||
BakeData *bake_data,
|
||||
float result[])
|
||||
{
|
||||
size_t num_pixels = bake_data->size();
|
||||
|
||||
int num_samples = aa_samples(scene, bake_data, shader_type);
|
||||
|
||||
/* calculate the total pixel samples for the progress bar */
|
||||
total_pixel_samples = 0;
|
||||
for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
|
||||
size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
|
||||
total_pixel_samples += shader_size * num_samples;
|
||||
}
|
||||
progress.reset_sample();
|
||||
progress.set_total_pixel_samples(total_pixel_samples);
|
||||
|
||||
/* needs to be up to date for baking specific AA samples */
|
||||
dscene->data.integrator.aa_samples = num_samples;
|
||||
device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
|
||||
|
||||
for (size_t shader_offset = 0; shader_offset < num_pixels; shader_offset += m_shader_limit) {
|
||||
size_t shader_size = (size_t)fminf(num_pixels - shader_offset, m_shader_limit);
|
||||
|
||||
/* setup input for device task */
|
||||
device_vector<uint4> d_input(device, "bake_input", MEM_READ_ONLY);
|
||||
uint4 *d_input_data = d_input.alloc(shader_size * 2);
|
||||
size_t d_input_size = 0;
|
||||
|
||||
for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
|
||||
d_input_data[d_input_size++] = bake_data->data(i);
|
||||
d_input_data[d_input_size++] = bake_data->differentials(i);
|
||||
}
|
||||
|
||||
if (d_input_size == 0) {
|
||||
m_is_baking = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* run device task */
|
||||
device_vector<float4> d_output(device, "bake_output", MEM_READ_WRITE);
|
||||
d_output.alloc(shader_size);
|
||||
d_output.zero_to_device();
|
||||
d_input.copy_to_device();
|
||||
|
||||
DeviceTask task(DeviceTask::SHADER);
|
||||
task.shader_input = d_input.device_pointer;
|
||||
task.shader_output = d_output.device_pointer;
|
||||
task.shader_eval_type = shader_type;
|
||||
task.shader_filter = pass_filter;
|
||||
task.shader_x = 0;
|
||||
task.offset = shader_offset;
|
||||
task.shader_w = d_output.size();
|
||||
task.num_samples = num_samples;
|
||||
task.get_cancel = function_bind(&Progress::get_cancel, &progress);
|
||||
task.update_progress_sample = function_bind(&Progress::add_samples_update, &progress, _1, _2);
|
||||
|
||||
device->task_add(task);
|
||||
device->task_wait();
|
||||
|
||||
if (progress.get_cancel()) {
|
||||
d_input.free();
|
||||
d_output.free();
|
||||
m_is_baking = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
d_output.copy_from_device(0, 1, d_output.size());
|
||||
d_input.free();
|
||||
|
||||
/* read result */
|
||||
int k = 0;
|
||||
|
||||
float4 *offset = d_output.data();
|
||||
|
||||
size_t depth = 4;
|
||||
for (size_t i = shader_offset; i < (shader_offset + shader_size); i++) {
|
||||
size_t index = i * depth;
|
||||
float4 out = offset[k++];
|
||||
|
||||
if (bake_data->is_valid(i)) {
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
result[index + j] = out[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d_output.free();
|
||||
}
|
||||
|
||||
m_is_baking = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void BakeManager::device_update(Device * /*device*/,
|
||||
DeviceScene * /*dscene*/,
|
||||
Scene * /*scene*/,
|
||||
Progress &progress)
|
||||
{
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
need_update = false;
|
||||
}
|
||||
|
||||
void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
|
||||
{
|
||||
}
|
||||
|
||||
int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type)
|
||||
static int aa_samples(Scene *scene, Object *object, ShaderEvalType type)
|
||||
{
|
||||
if (type == SHADER_EVAL_UV || type == SHADER_EVAL_ROUGHNESS) {
|
||||
return 1;
|
||||
}
|
||||
else if (type == SHADER_EVAL_NORMAL) {
|
||||
/* Only antialias normal if mesh has bump mapping. */
|
||||
Object *object = scene->objects[bake_data->object()];
|
||||
|
||||
if (object->geometry) {
|
||||
foreach (Shader *shader, object->geometry->used_shaders) {
|
||||
if (shader->has_bump) {
|
||||
@@ -269,7 +48,7 @@ int BakeManager::aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType ty
|
||||
}
|
||||
|
||||
/* Keep it synced with kernel_bake.h logic */
|
||||
int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter)
|
||||
static int shader_type_to_pass_filter(ShaderEvalType type, int pass_filter)
|
||||
{
|
||||
const int component_flags = pass_filter &
|
||||
(BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
|
||||
@@ -292,4 +71,84 @@ int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_
|
||||
}
|
||||
}
|
||||
|
||||
BakeManager::BakeManager()
|
||||
{
|
||||
type = SHADER_EVAL_BAKE;
|
||||
pass_filter = 0;
|
||||
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
BakeManager::~BakeManager()
|
||||
{
|
||||
}
|
||||
|
||||
bool BakeManager::get_baking()
|
||||
{
|
||||
return !object_name.empty();
|
||||
}
|
||||
|
||||
void BakeManager::set(Scene *scene,
|
||||
const std::string &object_name_,
|
||||
ShaderEvalType type_,
|
||||
int pass_filter_)
|
||||
{
|
||||
object_name = object_name_;
|
||||
type = type_;
|
||||
pass_filter = shader_type_to_pass_filter(type_, pass_filter_);
|
||||
|
||||
Pass::add(PASS_BAKE_PRIMITIVE, scene->film->passes);
|
||||
Pass::add(PASS_BAKE_DIFFERENTIAL, scene->film->passes);
|
||||
|
||||
if (type == SHADER_EVAL_UV) {
|
||||
/* force UV to be available */
|
||||
Pass::add(PASS_UV, scene->film->passes);
|
||||
}
|
||||
|
||||
/* force use_light_pass to be true if we bake more than just colors */
|
||||
if (pass_filter & ~BAKE_FILTER_COLOR) {
|
||||
Pass::add(PASS_LIGHT, scene->film->passes);
|
||||
}
|
||||
|
||||
/* create device and update scene */
|
||||
scene->film->tag_update(scene);
|
||||
scene->integrator->tag_update(scene);
|
||||
|
||||
need_update = true;
|
||||
}
|
||||
|
||||
void BakeManager::device_update(Device * /*device*/,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress & /* progress */)
|
||||
{
|
||||
if (!need_update)
|
||||
return;
|
||||
|
||||
KernelIntegrator *kintegrator = &dscene->data.integrator;
|
||||
KernelBake *kbake = &dscene->data.bake;
|
||||
|
||||
kbake->type = type;
|
||||
kbake->pass_filter = pass_filter;
|
||||
|
||||
int object_index = 0;
|
||||
foreach (Object *object, scene->objects) {
|
||||
const Geometry *geom = object->geometry;
|
||||
if (object->name == object_name && geom->type == Geometry::MESH) {
|
||||
kbake->object_index = object_index;
|
||||
kbake->tri_offset = geom->prim_offset;
|
||||
kintegrator->aa_samples = aa_samples(scene, object, type);
|
||||
break;
|
||||
}
|
||||
|
||||
object_index++;
|
||||
}
|
||||
|
||||
need_update = false;
|
||||
}
|
||||
|
||||
void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
|
||||
{
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -25,67 +25,23 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class BakeData {
|
||||
public:
|
||||
BakeData(const int object, const size_t tri_offset, const size_t num_pixels);
|
||||
~BakeData();
|
||||
|
||||
void set(int i, int prim, float uv[2], float dudx, float dudy, float dvdx, float dvdy);
|
||||
void set_null(int i);
|
||||
int object();
|
||||
size_t size();
|
||||
uint4 data(int i);
|
||||
uint4 differentials(int i);
|
||||
bool is_valid(int i);
|
||||
|
||||
private:
|
||||
int m_object;
|
||||
size_t m_tri_offset;
|
||||
size_t m_num_pixels;
|
||||
vector<int> m_primitive;
|
||||
vector<float> m_u;
|
||||
vector<float> m_v;
|
||||
vector<float> m_dudx;
|
||||
vector<float> m_dudy;
|
||||
vector<float> m_dvdx;
|
||||
vector<float> m_dvdy;
|
||||
};
|
||||
|
||||
class BakeManager {
|
||||
public:
|
||||
BakeManager();
|
||||
~BakeManager();
|
||||
|
||||
void set(Scene *scene, const std::string &object_name, ShaderEvalType type, int pass_filter);
|
||||
bool get_baking();
|
||||
void set_baking(const bool value);
|
||||
|
||||
BakeData *init(const int object, const size_t tri_offset, const size_t num_pixels);
|
||||
|
||||
void set_shader_limit(const size_t x, const size_t y);
|
||||
|
||||
bool bake(Device *device,
|
||||
DeviceScene *dscene,
|
||||
Scene *scene,
|
||||
Progress &progress,
|
||||
ShaderEvalType shader_type,
|
||||
const int pass_filter,
|
||||
BakeData *bake_data,
|
||||
float result[]);
|
||||
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
static int shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter);
|
||||
static int aa_samples(Scene *scene, BakeData *bake_data, ShaderEvalType type);
|
||||
|
||||
bool need_update;
|
||||
|
||||
size_t total_pixel_samples;
|
||||
|
||||
private:
|
||||
BakeData *m_bake_data;
|
||||
bool m_is_baking;
|
||||
size_t m_shader_limit;
|
||||
ShaderEvalType type;
|
||||
int pass_filter;
|
||||
std::string object_name;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -459,6 +459,40 @@ bool RenderBuffers::get_pass_rect(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RenderBuffers::set_pass_rect(PassType type, int components, float *pixels)
|
||||
{
|
||||
if (buffer.data() == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int pass_offset = 0;
|
||||
|
||||
for (size_t j = 0; j < params.passes.size(); j++) {
|
||||
Pass &pass = params.passes[j];
|
||||
|
||||
if (pass.type != type) {
|
||||
pass_offset += pass.components;
|
||||
continue;
|
||||
}
|
||||
|
||||
float *out = buffer.data() + pass_offset;
|
||||
int pass_stride = params.get_passes_size();
|
||||
int size = params.width * params.height;
|
||||
|
||||
assert(pass.components == components);
|
||||
|
||||
for (int i = 0; i < size; i++, out += pass_stride, pixels += components) {
|
||||
for (int j = 0; j < components; j++) {
|
||||
out[j] = pixels[j];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Display Buffer */
|
||||
|
||||
DisplayBuffer::DisplayBuffer(Device *device, bool linear)
|
||||
|
@@ -92,6 +92,7 @@ class RenderBuffers {
|
||||
const string &name, float exposure, int sample, int components, float *pixels);
|
||||
bool get_denoising_pass_rect(
|
||||
int offset, float exposure, int sample, int components, float *pixels);
|
||||
bool set_pass_rect(PassType type, int components, float *pixels);
|
||||
};
|
||||
|
||||
/* Display Buffer
|
||||
@@ -130,7 +131,7 @@ class DisplayBuffer {
|
||||
|
||||
class RenderTile {
|
||||
public:
|
||||
typedef enum { PATH_TRACE = (1 << 0), DENOISE = (1 << 1) } Task;
|
||||
typedef enum { PATH_TRACE = (1 << 0), BAKE = (1 << 1), DENOISE = (1 << 2) } Task;
|
||||
|
||||
Task task;
|
||||
int x, y, w, h;
|
||||
|
@@ -196,6 +196,10 @@ void Pass::add(PassType type, vector<Pass> &passes, const char *name)
|
||||
case PASS_AOV_VALUE:
|
||||
pass.components = 1;
|
||||
break;
|
||||
case PASS_BAKE_PRIMITIVE:
|
||||
case PASS_BAKE_DIFFERENTIAL:
|
||||
pass.components = 4;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
@@ -386,11 +390,13 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
if (pass.type <= PASS_CATEGORY_MAIN_END) {
|
||||
kfilm->pass_flag |= pass_flag;
|
||||
}
|
||||
else {
|
||||
assert(pass.type <= PASS_CATEGORY_LIGHT_END);
|
||||
else if (pass.type <= PASS_CATEGORY_LIGHT_END) {
|
||||
kfilm->use_light_pass = 1;
|
||||
kfilm->light_pass_flag |= pass_flag;
|
||||
}
|
||||
else {
|
||||
assert(pass.type <= PASS_CATEGORY_BAKE_END);
|
||||
}
|
||||
|
||||
switch (pass.type) {
|
||||
case PASS_COMBINED:
|
||||
@@ -471,6 +477,13 @@ void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
kfilm->pass_volume_direct = kfilm->pass_stride;
|
||||
break;
|
||||
|
||||
case PASS_BAKE_PRIMITIVE:
|
||||
kfilm->pass_bake_primitive = kfilm->pass_stride;
|
||||
break;
|
||||
case PASS_BAKE_DIFFERENTIAL:
|
||||
kfilm->pass_bake_differential = kfilm->pass_stride;
|
||||
break;
|
||||
|
||||
#ifdef WITH_CYCLES_DEBUG
|
||||
case PASS_BVH_TRAVERSED_NODES:
|
||||
kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
|
||||
|
@@ -204,10 +204,6 @@ class ShaderNode : public Node {
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool has_object_dependency()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool has_attribute_dependency()
|
||||
{
|
||||
return false;
|
||||
|
@@ -181,6 +181,7 @@ bool Light::has_contribution(Scene *scene)
|
||||
LightManager::LightManager()
|
||||
{
|
||||
need_update = true;
|
||||
need_update_background = true;
|
||||
use_light_visibility = false;
|
||||
}
|
||||
|
||||
@@ -901,7 +902,7 @@ void LightManager::device_update(Device *device,
|
||||
|
||||
VLOG(1) << "Total " << scene->lights.size() << " lights.";
|
||||
|
||||
device_free(device, dscene);
|
||||
device_free(device, dscene, need_update_background);
|
||||
|
||||
use_light_visibility = false;
|
||||
|
||||
@@ -915,9 +916,11 @@ void LightManager::device_update(Device *device,
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
device_update_background(device, dscene, scene, progress);
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
if (need_update_background) {
|
||||
device_update_background(device, dscene, scene, progress);
|
||||
if (progress.get_cancel())
|
||||
return;
|
||||
}
|
||||
|
||||
device_update_ies(dscene);
|
||||
if (progress.get_cancel())
|
||||
@@ -929,14 +932,17 @@ void LightManager::device_update(Device *device,
|
||||
}
|
||||
|
||||
need_update = false;
|
||||
need_update_background = false;
|
||||
}
|
||||
|
||||
void LightManager::device_free(Device *, DeviceScene *dscene)
|
||||
void LightManager::device_free(Device *, DeviceScene *dscene, const bool free_background)
|
||||
{
|
||||
dscene->light_distribution.free();
|
||||
dscene->lights.free();
|
||||
dscene->light_background_marginal_cdf.free();
|
||||
dscene->light_background_conditional_cdf.free();
|
||||
if (free_background) {
|
||||
dscene->light_background_marginal_cdf.free();
|
||||
dscene->light_background_conditional_cdf.free();
|
||||
}
|
||||
dscene->ies_lights.free();
|
||||
}
|
||||
|
||||
@@ -989,6 +995,7 @@ int LightManager::add_ies(const string &content)
|
||||
ies_slots[slot]->hash = hash;
|
||||
|
||||
need_update = true;
|
||||
need_update_background = true;
|
||||
|
||||
return slot;
|
||||
}
|
||||
@@ -1007,6 +1014,7 @@ void LightManager::remove_ies(int slot)
|
||||
|
||||
/* If the slot has no more users, update the device to remove it. */
|
||||
need_update |= (ies_slots[slot]->users == 0);
|
||||
need_update_background |= need_update;
|
||||
}
|
||||
|
||||
void LightManager::device_update_ies(DeviceScene *dscene)
|
||||
|
@@ -88,6 +88,9 @@ class LightManager {
|
||||
bool use_light_visibility;
|
||||
bool need_update;
|
||||
|
||||
/* Need to update background (including multiple importance map) */
|
||||
bool need_update_background;
|
||||
|
||||
LightManager();
|
||||
~LightManager();
|
||||
|
||||
@@ -97,7 +100,7 @@ class LightManager {
|
||||
void remove_ies(int slot);
|
||||
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
void device_free(Device *device, DeviceScene *dscene, const bool free_background = true);
|
||||
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
|
@@ -2166,12 +2166,11 @@ NODE_DEFINE(AnisotropicBsdfNode)
|
||||
SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
|
||||
|
||||
static NodeEnum distribution_enum;
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID);
|
||||
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
|
||||
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID);
|
||||
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID);
|
||||
SOCKET_ENUM(
|
||||
distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID);
|
||||
distribution_enum.insert("beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_ID);
|
||||
distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_ID);
|
||||
distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
|
||||
distribution_enum.insert("ashikhmin_shirley", CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID);
|
||||
SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_GGX_ID);
|
||||
|
||||
SOCKET_IN_VECTOR(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
|
||||
|
||||
@@ -2186,7 +2185,7 @@ NODE_DEFINE(AnisotropicBsdfNode)
|
||||
|
||||
AnisotropicBsdfNode::AnisotropicBsdfNode() : BsdfNode(node_type)
|
||||
{
|
||||
closure = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
|
||||
closure = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
}
|
||||
|
||||
void AnisotropicBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
@@ -2205,7 +2204,7 @@ void AnisotropicBsdfNode::compile(SVMCompiler &compiler)
|
||||
{
|
||||
closure = distribution;
|
||||
|
||||
if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID)
|
||||
if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
|
||||
BsdfNode::compile(
|
||||
compiler, input("Roughness"), input("Anisotropy"), input("Rotation"), input("Color"));
|
||||
else
|
||||
@@ -2299,7 +2298,7 @@ void GlossyBsdfNode::compile(SVMCompiler &compiler)
|
||||
if (closure == CLOSURE_BSDF_REFLECTION_ID)
|
||||
BsdfNode::compile(compiler, NULL, NULL);
|
||||
else if (closure == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID)
|
||||
BsdfNode::compile(compiler, input("Roughness"), NULL, input("Color"));
|
||||
BsdfNode::compile(compiler, input("Roughness"), NULL, NULL, input("Color"));
|
||||
else
|
||||
BsdfNode::compile(compiler, input("Roughness"), NULL);
|
||||
}
|
||||
|
@@ -359,10 +359,6 @@ class PointDensityTextureNode : public ShaderNode {
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool has_object_dependency()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Parameters. */
|
||||
ustring filename;
|
||||
@@ -896,10 +892,6 @@ class TextureCoordinateNode : public ShaderNode {
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool has_object_dependency()
|
||||
{
|
||||
return use_transform;
|
||||
}
|
||||
|
||||
float3 normal_osl;
|
||||
bool from_dupli;
|
||||
|
@@ -764,10 +764,6 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
|
||||
current_shader->has_volume_attribute_dependency = true;
|
||||
}
|
||||
|
||||
if (node->has_object_dependency()) {
|
||||
current_shader->has_object_dependency = true;
|
||||
}
|
||||
|
||||
if (node->has_integrator_dependency()) {
|
||||
current_shader->has_integrator_dependency = true;
|
||||
}
|
||||
@@ -1142,7 +1138,6 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
|
||||
shader->has_surface_spatial_varying = false;
|
||||
shader->has_volume_spatial_varying = false;
|
||||
shader->has_volume_attribute_dependency = false;
|
||||
shader->has_object_dependency = false;
|
||||
shader->has_integrator_dependency = false;
|
||||
|
||||
/* generate surface shader */
|
||||
|
@@ -410,7 +410,16 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
|
||||
rtile.num_samples = tile_manager.state.num_samples;
|
||||
rtile.resolution = tile_manager.state.resolution_divider;
|
||||
rtile.tile_index = tile->index;
|
||||
rtile.task = tile->state == Tile::DENOISE ? RenderTile::DENOISE : RenderTile::PATH_TRACE;
|
||||
|
||||
if (tile->state == Tile::DENOISE) {
|
||||
rtile.task = RenderTile::DENOISE;
|
||||
}
|
||||
else if (read_bake_tile_cb) {
|
||||
rtile.task = RenderTile::BAKE;
|
||||
}
|
||||
else {
|
||||
rtile.task = RenderTile::PATH_TRACE;
|
||||
}
|
||||
|
||||
tile_lock.unlock();
|
||||
|
||||
@@ -451,11 +460,20 @@ bool Session::acquire_tile(RenderTile &rtile, Device *tile_device, uint tile_typ
|
||||
rtile.buffers = tile->buffers;
|
||||
rtile.sample = tile_manager.state.sample;
|
||||
|
||||
/* this will tag tile as IN PROGRESS in blender-side render pipeline,
|
||||
* which is needed to highlight currently rendering tile before first
|
||||
* sample was processed for it
|
||||
*/
|
||||
update_tile_sample(rtile);
|
||||
if (read_bake_tile_cb) {
|
||||
/* This will read any passes needed as input for baking. */
|
||||
{
|
||||
thread_scoped_lock tile_lock(tile_mutex);
|
||||
read_bake_tile_cb(rtile);
|
||||
}
|
||||
rtile.buffers->buffer.copy_to_device();
|
||||
}
|
||||
else {
|
||||
/* This will tag tile as IN PROGRESS in blender-side render pipeline,
|
||||
* which is needed to highlight currently rendering tile before first
|
||||
* sample was processed for it. */
|
||||
update_tile_sample(rtile);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -484,6 +502,7 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise)
|
||||
bool delete_tile;
|
||||
|
||||
if (tile_manager.finish_tile(rtile.tile_index, need_denoise, delete_tile)) {
|
||||
/* Finished tile pixels write. */
|
||||
if (write_render_tile_cb && params.progressive_refine == false) {
|
||||
write_render_tile_cb(rtile);
|
||||
}
|
||||
@@ -494,6 +513,7 @@ void Session::release_tile(RenderTile &rtile, const bool need_denoise)
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* In progress tile pixels update. */
|
||||
if (update_render_tile_cb && params.progressive_refine == false) {
|
||||
update_render_tile_cb(rtile, false);
|
||||
}
|
||||
|
@@ -148,6 +148,7 @@ class Session {
|
||||
|
||||
function<void(RenderTile &)> write_render_tile_cb;
|
||||
function<void(RenderTile &, bool)> update_render_tile_cb;
|
||||
function<void(RenderTile &)> read_bake_tile_cb;
|
||||
|
||||
explicit Session(const SessionParams ¶ms);
|
||||
~Session();
|
||||
|
@@ -206,7 +206,6 @@ Shader::Shader() : Node(node_type)
|
||||
has_surface_spatial_varying = false;
|
||||
has_volume_spatial_varying = false;
|
||||
has_volume_attribute_dependency = false;
|
||||
has_object_dependency = false;
|
||||
has_integrator_dependency = false;
|
||||
has_volume_connected = false;
|
||||
prev_volume_step_rate = 0.0f;
|
||||
@@ -218,7 +217,6 @@ Shader::Shader() : Node(node_type)
|
||||
|
||||
need_update = true;
|
||||
need_update_geometry = true;
|
||||
need_sync_object = false;
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
@@ -320,9 +318,11 @@ void Shader::tag_update(Scene *scene)
|
||||
* has use_mis set to false. We are quite close to release now, so
|
||||
* better to be safe.
|
||||
*/
|
||||
if (this == scene->background->get_shader(scene) &&
|
||||
scene->light_manager->has_background_light(scene)) {
|
||||
scene->light_manager->need_update = true;
|
||||
if (this == scene->background->get_shader(scene)) {
|
||||
scene->light_manager->need_update_background = true;
|
||||
if (scene->light_manager->has_background_light(scene)) {
|
||||
scene->light_manager->need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* quick detection of which kind of shaders we have to avoid loading
|
||||
|
@@ -98,7 +98,6 @@ class Shader : public Node {
|
||||
/* synchronization */
|
||||
bool need_update;
|
||||
bool need_update_geometry;
|
||||
bool need_sync_object;
|
||||
|
||||
/* If the shader has only volume components, the surface is assumed to
|
||||
* be transparent.
|
||||
@@ -121,7 +120,6 @@ class Shader : public Node {
|
||||
bool has_surface_spatial_varying;
|
||||
bool has_volume_spatial_varying;
|
||||
bool has_volume_attribute_dependency;
|
||||
bool has_object_dependency;
|
||||
bool has_integrator_dependency;
|
||||
|
||||
/* displacement */
|
||||
|
@@ -448,10 +448,6 @@ void SVMCompiler::generate_node(ShaderNode *node, ShaderNodeSet &done)
|
||||
current_shader->has_volume_attribute_dependency = true;
|
||||
}
|
||||
|
||||
if (node->has_object_dependency()) {
|
||||
current_shader->has_object_dependency = true;
|
||||
}
|
||||
|
||||
if (node->has_integrator_dependency()) {
|
||||
current_shader->has_integrator_dependency = true;
|
||||
}
|
||||
@@ -863,7 +859,6 @@ void SVMCompiler::compile(Shader *shader, array<int4> &svm_nodes, int index, Sum
|
||||
shader->has_surface_spatial_varying = false;
|
||||
shader->has_volume_spatial_varying = false;
|
||||
shader->has_volume_attribute_dependency = false;
|
||||
shader->has_object_dependency = false;
|
||||
shader->has_integrator_dependency = false;
|
||||
|
||||
/* generate bump shader */
|
||||
|
@@ -23,8 +23,8 @@
|
||||
|
||||
#include "GHOST_System.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <stdio.h> /* just for printf */
|
||||
#include <time.h>
|
||||
|
||||
#include "GHOST_DisplayManager.h"
|
||||
#include "GHOST_EventManager.h"
|
||||
@@ -58,12 +58,9 @@ GHOST_System::~GHOST_System()
|
||||
|
||||
GHOST_TUns64 GHOST_System::getMilliSeconds() const
|
||||
{
|
||||
GHOST_TUns64 millis = ::clock();
|
||||
if (CLOCKS_PER_SEC != 1000) {
|
||||
millis *= 1000;
|
||||
millis /= CLOCKS_PER_SEC;
|
||||
}
|
||||
return millis;
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::steady_clock::now().time_since_epoch())
|
||||
.count();
|
||||
}
|
||||
|
||||
GHOST_ITimerTask *GHOST_System::installTimer(GHOST_TUns64 delay,
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "GHOST_EventDragnDrop.h"
|
||||
#include "GHOST_EventKey.h"
|
||||
#include "GHOST_EventWheel.h"
|
||||
#include "GHOST_TimerManager.h"
|
||||
#include "GHOST_WindowManager.h"
|
||||
|
||||
#include "GHOST_ContextEGL.h"
|
||||
@@ -34,7 +35,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -91,6 +92,13 @@ struct data_source_t {
|
||||
char *buffer_out;
|
||||
};
|
||||
|
||||
struct key_repeat_payload_t {
|
||||
GHOST_SystemWayland *system;
|
||||
GHOST_IWindow *window;
|
||||
GHOST_TKey key;
|
||||
GHOST_TEventKeyData key_data;
|
||||
};
|
||||
|
||||
struct input_t {
|
||||
GHOST_SystemWayland *system;
|
||||
|
||||
@@ -109,6 +117,17 @@ struct input_t {
|
||||
|
||||
struct xkb_context *xkb_context;
|
||||
struct xkb_state *xkb_state;
|
||||
struct {
|
||||
/* Key repetition in character per second. */
|
||||
int32_t rate;
|
||||
/* Time (milliseconds) after which to start repeating keys. */
|
||||
int32_t delay;
|
||||
/* Timer for key repeats. */
|
||||
GHOST_ITimerTask *timer = nullptr;
|
||||
} key_repeat;
|
||||
|
||||
struct wl_surface *focus_pointer = nullptr;
|
||||
struct wl_surface *focus_keyboard = nullptr;
|
||||
|
||||
struct wl_data_device *data_device = nullptr;
|
||||
struct data_offer_t *data_offer_dnd; /* Drag & Drop. */
|
||||
@@ -174,6 +193,11 @@ static void display_destroy(display_t *d)
|
||||
}
|
||||
}
|
||||
if (input->keyboard) {
|
||||
if (input->key_repeat.timer) {
|
||||
delete static_cast<key_repeat_payload_t *>(input->key_repeat.timer->getUserData());
|
||||
input->system->removeTimer(input->key_repeat.timer);
|
||||
input->key_repeat.timer = nullptr;
|
||||
}
|
||||
wl_keyboard_destroy(input->keyboard);
|
||||
}
|
||||
if (input->xkb_state) {
|
||||
@@ -420,22 +444,26 @@ static void relative_pointer_relative_motion(
|
||||
input->x += wl_fixed_to_int(dx);
|
||||
input->y += wl_fixed_to_int(dy);
|
||||
|
||||
input->system->pushEvent(
|
||||
new GHOST_EventCursor(input->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
input->system->getWindowManager()->getActiveWindow(),
|
||||
input->x,
|
||||
input->y,
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
||||
wl_surface_get_user_data(input->focus_pointer));
|
||||
|
||||
input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
input->x,
|
||||
input->y,
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
}
|
||||
|
||||
static const zwp_relative_pointer_v1_listener relative_pointer_listener = {
|
||||
relative_pointer_relative_motion};
|
||||
relative_pointer_relative_motion,
|
||||
};
|
||||
|
||||
static void dnd_events(const input_t *const input, const GHOST_TEventType event)
|
||||
{
|
||||
const GHOST_TUns64 time = input->system->getMilliSeconds();
|
||||
GHOST_IWindow *const window = input->system->getWindowManager()->getActiveWindow();
|
||||
GHOST_IWindow *const window = static_cast<GHOST_WindowWayland *>(
|
||||
wl_surface_get_user_data(input->focus_pointer));
|
||||
for (const std::string &type : mime_preference_order) {
|
||||
input->system->pushEvent(new GHOST_EventDragnDrop(time,
|
||||
event,
|
||||
@@ -641,7 +669,7 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
|
||||
data_offer->types.begin(),
|
||||
data_offer->types.end());
|
||||
|
||||
auto read_uris = [](GHOST_SystemWayland *const system,
|
||||
auto read_uris = [](input_t *const input,
|
||||
data_offer_t *data_offer,
|
||||
const std::string mime_receive) {
|
||||
const int x = data_offer->dnd.x;
|
||||
@@ -655,6 +683,8 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
|
||||
delete data_offer;
|
||||
data_offer = nullptr;
|
||||
|
||||
GHOST_SystemWayland *const system = input->system;
|
||||
|
||||
if (mime_receive == mime_text_uri) {
|
||||
static constexpr const char *file_proto = "file://";
|
||||
static constexpr const char *crlf = "\r\n";
|
||||
@@ -683,10 +713,12 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
|
||||
malloc((uris[i].size() + 1) * sizeof(GHOST_TUns8)));
|
||||
memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1);
|
||||
}
|
||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
||||
wl_surface_get_user_data(input->focus_pointer));
|
||||
system->pushEvent(new GHOST_EventDragnDrop(system->getMilliSeconds(),
|
||||
GHOST_kEventDraggingDropDone,
|
||||
GHOST_kDragnDropTypeFilenames,
|
||||
system->getWindowManager()->getActiveWindow(),
|
||||
win,
|
||||
x,
|
||||
y,
|
||||
flist));
|
||||
@@ -698,7 +730,7 @@ static void data_device_drop(void *data, struct wl_data_device * /*wl_data_devic
|
||||
wl_display_roundtrip(system->display());
|
||||
};
|
||||
|
||||
std::thread read_thread(read_uris, input->system, data_offer, mime_receive);
|
||||
std::thread read_thread(read_uris, input, data_offer, mime_receive);
|
||||
read_thread.detach();
|
||||
}
|
||||
|
||||
@@ -778,17 +810,24 @@ static void pointer_enter(void *data,
|
||||
input->pointer_serial = serial;
|
||||
input->x = wl_fixed_to_int(surface_x);
|
||||
input->y = wl_fixed_to_int(surface_y);
|
||||
input->focus_pointer = surface;
|
||||
|
||||
static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface))->activate();
|
||||
input->system->pushEvent(
|
||||
new GHOST_EventCursor(input->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface)),
|
||||
input->x,
|
||||
input->y,
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
}
|
||||
|
||||
static void pointer_leave(void * /*data*/,
|
||||
static void pointer_leave(void *data,
|
||||
struct wl_pointer * /*wl_pointer*/,
|
||||
uint32_t /*serial*/,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
if (surface != nullptr) {
|
||||
static_cast<GHOST_WindowWayland *>(wl_surface_get_user_data(surface))->deactivate();
|
||||
static_cast<input_t *>(data)->focus_pointer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -800,16 +839,22 @@ static void pointer_motion(void *data,
|
||||
{
|
||||
input_t *input = static_cast<input_t *>(data);
|
||||
|
||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
||||
wl_surface_get_user_data(input->focus_pointer));
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
input->x = wl_fixed_to_int(surface_x);
|
||||
input->y = wl_fixed_to_int(surface_y);
|
||||
|
||||
input->system->pushEvent(
|
||||
new GHOST_EventCursor(input->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
input->system->getWindowManager()->getActiveWindow(),
|
||||
wl_fixed_to_int(surface_x),
|
||||
wl_fixed_to_int(surface_y),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
input->system->pushEvent(new GHOST_EventCursor(input->system->getMilliSeconds(),
|
||||
GHOST_kEventCursorMove,
|
||||
win,
|
||||
wl_fixed_to_int(surface_x),
|
||||
wl_fixed_to_int(surface_y),
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
}
|
||||
|
||||
static void pointer_button(void *data,
|
||||
@@ -843,14 +888,12 @@ static void pointer_button(void *data,
|
||||
}
|
||||
|
||||
input_t *input = static_cast<input_t *>(data);
|
||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
||||
wl_surface_get_user_data(input->focus_pointer));
|
||||
input->data_source->source_serial = serial;
|
||||
input->buttons.set(ebutton, state == WL_POINTER_BUTTON_STATE_PRESSED);
|
||||
input->system->pushEvent(
|
||||
new GHOST_EventButton(input->system->getMilliSeconds(),
|
||||
etype,
|
||||
input->system->getWindowManager()->getActiveWindow(),
|
||||
ebutton,
|
||||
GHOST_TABLET_DATA_NONE));
|
||||
input->system->pushEvent(new GHOST_EventButton(
|
||||
input->system->getMilliSeconds(), etype, win, ebutton, GHOST_TABLET_DATA_NONE));
|
||||
}
|
||||
|
||||
static void pointer_axis(void *data,
|
||||
@@ -863,10 +906,10 @@ static void pointer_axis(void *data,
|
||||
return;
|
||||
}
|
||||
input_t *input = static_cast<input_t *>(data);
|
||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
||||
wl_surface_get_user_data(input->focus_pointer));
|
||||
input->system->pushEvent(
|
||||
new GHOST_EventWheel(input->system->getMilliSeconds(),
|
||||
input->system->getWindowManager()->getActiveWindow(),
|
||||
std::signbit(value) ? +1 : -1));
|
||||
new GHOST_EventWheel(input->system->getMilliSeconds(), win, std::signbit(value) ? +1 : -1));
|
||||
}
|
||||
|
||||
static const struct wl_pointer_listener pointer_listener = {
|
||||
@@ -913,13 +956,15 @@ static void keyboard_keymap(
|
||||
* Notification that this seat's keyboard focus is on a certain
|
||||
* surface.
|
||||
*/
|
||||
static void keyboard_enter(void * /*data*/,
|
||||
static void keyboard_enter(void *data,
|
||||
struct wl_keyboard * /*wl_keyboard*/,
|
||||
uint32_t /*serial*/,
|
||||
struct wl_surface * /*surface*/,
|
||||
struct wl_surface *surface,
|
||||
struct wl_array * /*keys*/)
|
||||
{
|
||||
/* pass */
|
||||
if (surface != nullptr) {
|
||||
static_cast<input_t *>(data)->focus_keyboard = surface;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -928,12 +973,14 @@ static void keyboard_enter(void * /*data*/,
|
||||
* Notification that this seat's keyboard focus is no longer on a
|
||||
* certain surface.
|
||||
*/
|
||||
static void keyboard_leave(void * /*data*/,
|
||||
static void keyboard_leave(void *data,
|
||||
struct wl_keyboard * /*wl_keyboard*/,
|
||||
uint32_t /*serial*/,
|
||||
struct wl_surface * /*surface*/)
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
/* pass */
|
||||
if (surface != nullptr) {
|
||||
static_cast<input_t *>(data)->focus_keyboard = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -988,6 +1035,14 @@ static void keyboard_key(void *data,
|
||||
}
|
||||
const GHOST_TKey gkey = xkb_map_gkey(sym);
|
||||
|
||||
/* Delete previous timer. */
|
||||
if (xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key + 8) &&
|
||||
input->key_repeat.timer) {
|
||||
delete static_cast<key_repeat_payload_t *>(input->key_repeat.timer->getUserData());
|
||||
input->system->removeTimer(input->key_repeat.timer);
|
||||
input->key_repeat.timer = nullptr;
|
||||
}
|
||||
|
||||
GHOST_TEventKeyData key_data;
|
||||
|
||||
if (etype == GHOST_kEventKeyDown) {
|
||||
@@ -999,13 +1054,38 @@ static void keyboard_key(void *data,
|
||||
}
|
||||
|
||||
input->data_source->source_serial = serial;
|
||||
input->system->pushEvent(new GHOST_EventKey(input->system->getMilliSeconds(),
|
||||
etype,
|
||||
input->system->getWindowManager()->getActiveWindow(),
|
||||
gkey,
|
||||
'\0',
|
||||
key_data.utf8_buf,
|
||||
false));
|
||||
|
||||
GHOST_IWindow *win = static_cast<GHOST_WindowWayland *>(
|
||||
wl_surface_get_user_data(input->focus_keyboard));
|
||||
input->system->pushEvent(new GHOST_EventKey(
|
||||
input->system->getMilliSeconds(), etype, win, gkey, '\0', key_data.utf8_buf, false));
|
||||
|
||||
/* Start timer for repeating key, if applicable. */
|
||||
if (input->key_repeat.rate > 0 &&
|
||||
xkb_keymap_key_repeats(xkb_state_get_keymap(input->xkb_state), key + 8) &&
|
||||
etype == GHOST_kEventKeyDown) {
|
||||
|
||||
key_repeat_payload_t *payload = new key_repeat_payload_t({
|
||||
.system = input->system,
|
||||
.window = win,
|
||||
.key = gkey,
|
||||
.key_data = key_data,
|
||||
});
|
||||
|
||||
auto cb = [](GHOST_ITimerTask *task, GHOST_TUns64 /*time*/) {
|
||||
struct key_repeat_payload_t *payload = static_cast<key_repeat_payload_t *>(
|
||||
task->getUserData());
|
||||
payload->system->pushEvent(new GHOST_EventKey(payload->system->getMilliSeconds(),
|
||||
GHOST_kEventKeyDown,
|
||||
payload->window,
|
||||
payload->key,
|
||||
'\0',
|
||||
payload->key_data.utf8_buf,
|
||||
true));
|
||||
};
|
||||
input->key_repeat.timer = input->system->installTimer(
|
||||
input->key_repeat.delay, 1000 / input->key_repeat.rate, cb, payload);
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_modifiers(void *data,
|
||||
@@ -1025,12 +1105,24 @@ static void keyboard_modifiers(void *data,
|
||||
group);
|
||||
}
|
||||
|
||||
static void keyboard_repeat_info(void *data,
|
||||
struct wl_keyboard * /*wl_keyboard*/,
|
||||
int32_t rate,
|
||||
int32_t delay)
|
||||
{
|
||||
input_t *input = static_cast<input_t *>(data);
|
||||
|
||||
input->key_repeat.rate = rate;
|
||||
input->key_repeat.delay = delay;
|
||||
}
|
||||
|
||||
static const struct wl_keyboard_listener keyboard_listener = {
|
||||
keyboard_keymap,
|
||||
keyboard_enter,
|
||||
keyboard_leave,
|
||||
keyboard_key,
|
||||
keyboard_modifiers,
|
||||
keyboard_repeat_info,
|
||||
};
|
||||
|
||||
static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t capabilities)
|
||||
@@ -1163,7 +1255,7 @@ static void global_add(void *data,
|
||||
input->relative_pointer = nullptr;
|
||||
input->locked_pointer = nullptr;
|
||||
input->seat = static_cast<wl_seat *>(
|
||||
wl_registry_bind(wl_registry, name, &wl_seat_interface, 2));
|
||||
wl_registry_bind(wl_registry, name, &wl_seat_interface, 4));
|
||||
display->inputs.push_back(input);
|
||||
wl_seat_add_listener(input->seat, &seat_listener, input);
|
||||
}
|
||||
@@ -1260,10 +1352,18 @@ GHOST_SystemWayland::~GHOST_SystemWayland()
|
||||
display_destroy(d);
|
||||
}
|
||||
|
||||
bool GHOST_SystemWayland::processEvents(bool /*waitForEvent*/)
|
||||
bool GHOST_SystemWayland::processEvents(bool waitForEvent)
|
||||
{
|
||||
wl_display_dispatch(d->display);
|
||||
return true;
|
||||
const bool fired = getTimerManager()->fireTimers(getMilliSeconds());
|
||||
|
||||
if (waitForEvent) {
|
||||
wl_display_dispatch(d->display);
|
||||
}
|
||||
else {
|
||||
wl_display_roundtrip(d->display);
|
||||
}
|
||||
|
||||
return fired || (getEventManager()->getNumEvents() > 0);
|
||||
}
|
||||
|
||||
int GHOST_SystemWayland::toggleConsole(int /*action*/)
|
||||
@@ -1352,7 +1452,7 @@ GHOST_TUns8 GHOST_SystemWayland::getNumDisplays() const
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWayland::getCursorPosition(GHOST_TInt32 &x, GHOST_TInt32 &y) const
|
||||
{
|
||||
if (getWindowManager()->getActiveWindow() != nullptr && !d->inputs.empty()) {
|
||||
if (!d->inputs.empty() && (d->inputs[0]->focus_pointer != nullptr)) {
|
||||
x = d->inputs[0]->x;
|
||||
y = d->inputs[0]->y;
|
||||
return GHOST_kSuccess;
|
||||
|
@@ -53,6 +53,14 @@ if(WIN32 AND NOT UNIX)
|
||||
|
||||
mmap_win.h
|
||||
)
|
||||
|
||||
list(APPEND INC_SYS
|
||||
${PTHREADS_INC}
|
||||
)
|
||||
|
||||
list(APPEND LIB
|
||||
${PTHREADS_LIBRARIES}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Jemalloc 5.0.0+ needs extra configuration.
|
||||
|
@@ -145,14 +145,6 @@ extern void *(*MEM_mallocN_aligned)(size_t len,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
|
||||
/**
|
||||
* Same as callocN, clears memory and uses mmap (disk cached) if supported.
|
||||
* Can be free'd with MEM_freeN as usual.
|
||||
* */
|
||||
extern void *(*MEM_mapallocN)(size_t len,
|
||||
const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
|
||||
|
||||
/** Print a list of the names and sizes of all allocated memory
|
||||
* blocks. as a python dict for easy investigation */
|
||||
extern void (*MEM_printmemlist_pydict)(void);
|
||||
@@ -176,20 +168,11 @@ extern void (*MEM_set_error_callback)(void (*func)(const char *));
|
||||
* @retval true for correct memory, false for corrupted memory. */
|
||||
extern bool (*MEM_consistency_check)(void);
|
||||
|
||||
/** Set thread locking functions for safe memory allocation from multiple
|
||||
* threads, pass NULL pointers to disable thread locking again. */
|
||||
extern void (*MEM_set_lock_callback)(void (*lock)(void), void (*unlock)(void));
|
||||
|
||||
/** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */
|
||||
extern void (*MEM_set_memory_debug)(void);
|
||||
|
||||
/**
|
||||
* Memory usage stats
|
||||
* - MEM_get_memory_in_use is all memory
|
||||
* - MEM_get_mapped_memory_in_use is a subset of all memory */
|
||||
/** Memory usage stats. */
|
||||
extern size_t (*MEM_get_memory_in_use)(void);
|
||||
/** Get mapped memory usage. */
|
||||
extern size_t (*MEM_get_mapped_memory_in_use)(void);
|
||||
/** Get amount of memory blocks in use. */
|
||||
extern unsigned int (*MEM_get_memory_blocks_in_use)(void);
|
||||
|
||||
|
@@ -48,18 +48,14 @@ void *(*MEM_malloc_arrayN)(size_t len, size_t size, const char *str) = MEM_lockf
|
||||
void *(*MEM_mallocN_aligned)(size_t len,
|
||||
size_t alignment,
|
||||
const char *str) = MEM_lockfree_mallocN_aligned;
|
||||
void *(*MEM_mapallocN)(size_t len, const char *str) = MEM_lockfree_mapallocN;
|
||||
void (*MEM_printmemlist_pydict)(void) = MEM_lockfree_printmemlist_pydict;
|
||||
void (*MEM_printmemlist)(void) = MEM_lockfree_printmemlist;
|
||||
void (*MEM_callbackmemlist)(void (*func)(void *)) = MEM_lockfree_callbackmemlist;
|
||||
void (*MEM_printmemlist_stats)(void) = MEM_lockfree_printmemlist_stats;
|
||||
void (*MEM_set_error_callback)(void (*func)(const char *)) = MEM_lockfree_set_error_callback;
|
||||
bool (*MEM_consistency_check)(void) = MEM_lockfree_consistency_check;
|
||||
void (*MEM_set_lock_callback)(void (*lock)(void),
|
||||
void (*unlock)(void)) = MEM_lockfree_set_lock_callback;
|
||||
void (*MEM_set_memory_debug)(void) = MEM_lockfree_set_memory_debug;
|
||||
size_t (*MEM_get_memory_in_use)(void) = MEM_lockfree_get_memory_in_use;
|
||||
size_t (*MEM_get_mapped_memory_in_use)(void) = MEM_lockfree_get_mapped_memory_in_use;
|
||||
unsigned int (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
|
||||
void (*MEM_reset_peak_memory)(void) = MEM_lockfree_reset_peak_memory;
|
||||
size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;
|
||||
@@ -111,17 +107,14 @@ void MEM_use_guarded_allocator(void)
|
||||
MEM_mallocN = MEM_guarded_mallocN;
|
||||
MEM_malloc_arrayN = MEM_guarded_malloc_arrayN;
|
||||
MEM_mallocN_aligned = MEM_guarded_mallocN_aligned;
|
||||
MEM_mapallocN = MEM_guarded_mapallocN;
|
||||
MEM_printmemlist_pydict = MEM_guarded_printmemlist_pydict;
|
||||
MEM_printmemlist = MEM_guarded_printmemlist;
|
||||
MEM_callbackmemlist = MEM_guarded_callbackmemlist;
|
||||
MEM_printmemlist_stats = MEM_guarded_printmemlist_stats;
|
||||
MEM_set_error_callback = MEM_guarded_set_error_callback;
|
||||
MEM_consistency_check = MEM_guarded_consistency_check;
|
||||
MEM_set_lock_callback = MEM_guarded_set_lock_callback;
|
||||
MEM_set_memory_debug = MEM_guarded_set_memory_debug;
|
||||
MEM_get_memory_in_use = MEM_guarded_get_memory_in_use;
|
||||
MEM_get_mapped_memory_in_use = MEM_guarded_get_mapped_memory_in_use;
|
||||
MEM_get_memory_blocks_in_use = MEM_guarded_get_memory_blocks_in_use;
|
||||
MEM_reset_peak_memory = MEM_guarded_reset_peak_memory;
|
||||
MEM_get_peak_memory = MEM_guarded_get_peak_memory;
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include <string.h> /* memcpy */
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
/* to ensure strict conversions */
|
||||
@@ -50,17 +52,6 @@
|
||||
|
||||
//#define DEBUG_MEMCOUNTER
|
||||
|
||||
/* Only for debugging:
|
||||
* defining DEBUG_THREADS will enable check whether memory manager
|
||||
* is locked with a mutex when allocation is called from non-main
|
||||
* thread.
|
||||
*
|
||||
* This helps troubleshooting memory issues caused by the fact
|
||||
* guarded allocator is not thread-safe, however this check will
|
||||
* fail to check allocations from openmp threads.
|
||||
*/
|
||||
//#define DEBUG_THREADS
|
||||
|
||||
/* Only for debugging:
|
||||
* Defining DEBUG_BACKTRACE will store a backtrace from where
|
||||
* memory block was allocated and print this trace for all
|
||||
@@ -104,7 +95,7 @@ typedef struct MemHead {
|
||||
const char *name;
|
||||
const char *nextname;
|
||||
int tag2;
|
||||
short mmap; /* if true, memory was mmapped */
|
||||
short pad1;
|
||||
short alignment; /* if non-zero aligned alloc was used
|
||||
* and alignment is stored here.
|
||||
*/
|
||||
@@ -124,24 +115,6 @@ typedef struct MemHead {
|
||||
|
||||
typedef MemHead MemHeadAligned;
|
||||
|
||||
/* for openmp threading asserts, saves time troubleshooting
|
||||
* we may need to extend this if blender code starts using MEM_
|
||||
* functions inside OpenMP correctly with omp_set_lock() */
|
||||
|
||||
#if 0 /* disable for now, only use to debug openmp code which doesn lock threads for malloc */
|
||||
# if defined(_OPENMP) && defined(DEBUG)
|
||||
# include <assert.h>
|
||||
# include <omp.h>
|
||||
# define DEBUG_OMP_MALLOC
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_THREADS
|
||||
# include <assert.h>
|
||||
# include <pthread.h>
|
||||
static pthread_t mainid;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_BACKTRACE
|
||||
# if defined(__linux__) || defined(__APPLE__)
|
||||
# include <execinfo.h>
|
||||
@@ -187,13 +160,11 @@ static const char *check_memlist(MemHead *memh);
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static unsigned int totblock = 0;
|
||||
static size_t mem_in_use = 0, mmap_in_use = 0, peak_mem = 0;
|
||||
static size_t mem_in_use = 0, peak_mem = 0;
|
||||
|
||||
static volatile struct localListBase _membase;
|
||||
static volatile struct localListBase *membase = &_membase;
|
||||
static void (*error_callback)(const char *) = NULL;
|
||||
static void (*thread_lock_callback)(void) = NULL;
|
||||
static void (*thread_unlock_callback)(void) = NULL;
|
||||
|
||||
static bool malloc_debug_memset = false;
|
||||
|
||||
@@ -233,40 +204,16 @@ print_error(const char *str, ...)
|
||||
fputs(buf, stderr);
|
||||
}
|
||||
|
||||
static pthread_mutex_t thread_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void mem_lock_thread(void)
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
static int initialized = 0;
|
||||
|
||||
if (initialized == 0) {
|
||||
/* assume first allocation happens from main thread */
|
||||
mainid = pthread_self();
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
|
||||
assert(!"Memory function is called from non-main thread without lock");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_OMP_MALLOC
|
||||
assert(omp_in_parallel() == 0);
|
||||
#endif
|
||||
|
||||
if (thread_lock_callback)
|
||||
thread_lock_callback();
|
||||
pthread_mutex_lock(&thread_lock);
|
||||
}
|
||||
|
||||
static void mem_unlock_thread(void)
|
||||
{
|
||||
#ifdef DEBUG_THREADS
|
||||
if (!pthread_equal(pthread_self(), mainid) && thread_lock_callback == NULL) {
|
||||
assert(!"Thread lock was removed while allocation from thread is in progress");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (thread_unlock_callback)
|
||||
thread_unlock_callback();
|
||||
pthread_mutex_unlock(&thread_lock);
|
||||
}
|
||||
|
||||
bool MEM_guarded_consistency_check(void)
|
||||
@@ -287,12 +234,6 @@ void MEM_guarded_set_error_callback(void (*func)(const char *))
|
||||
error_callback = func;
|
||||
}
|
||||
|
||||
void MEM_guarded_set_lock_callback(void (*lock)(void), void (*unlock)(void))
|
||||
{
|
||||
thread_lock_callback = lock;
|
||||
thread_unlock_callback = unlock;
|
||||
}
|
||||
|
||||
void MEM_guarded_set_memory_debug(void)
|
||||
{
|
||||
malloc_debug_memset = true;
|
||||
@@ -320,10 +261,8 @@ void *MEM_guarded_dupallocN(const void *vmemh)
|
||||
memh--;
|
||||
|
||||
#ifndef DEBUG_MEMDUPLINAME
|
||||
if (UNLIKELY(memh->mmap))
|
||||
newp = MEM_guarded_mapallocN(memh->len, "dupli_mapalloc");
|
||||
else if (LIKELY(memh->alignment == 0))
|
||||
newp = MEM_guarded_mapallocN(memh->len, "dupli_mapalloc");
|
||||
if (LIKELY(memh->alignment == 0))
|
||||
newp = MEM_guarded_mallocN(memh->len, "dupli_alloc");
|
||||
else
|
||||
newp = MEM_guarded_mallocN_aligned(memh->len, (size_t)memh->alignment, "dupli_alloc");
|
||||
|
||||
@@ -334,11 +273,7 @@ void *MEM_guarded_dupallocN(const void *vmemh)
|
||||
MemHead *nmemh;
|
||||
char *name = malloc(strlen(memh->name) + 24);
|
||||
|
||||
if (UNLIKELY(memh->mmap)) {
|
||||
sprintf(name, "%s %s", "dupli_mapalloc", memh->name);
|
||||
newp = MEM_guarded_mapallocN(memh->len, name);
|
||||
}
|
||||
else if (LIKELY(memh->alignment == 0)) {
|
||||
if (LIKELY(memh->alignment == 0)) {
|
||||
sprintf(name, "%s %s", "dupli_alloc", memh->name);
|
||||
newp = MEM_guarded_mallocN(memh->len, name);
|
||||
}
|
||||
@@ -478,7 +413,7 @@ static void make_memhead_header(MemHead *memh, size_t len, const char *str)
|
||||
memh->name = str;
|
||||
memh->nextname = NULL;
|
||||
memh->len = len;
|
||||
memh->mmap = 0;
|
||||
memh->pad1 = 0;
|
||||
memh->alignment = 0;
|
||||
memh->tag2 = MEMTAG2;
|
||||
|
||||
@@ -646,58 +581,6 @@ void *MEM_guarded_calloc_arrayN(size_t len, size_t size, const char *str)
|
||||
return MEM_guarded_callocN(total_size, str);
|
||||
}
|
||||
|
||||
/* note; mmap returns zero'd memory */
|
||||
void *MEM_guarded_mapallocN(size_t len, const char *str)
|
||||
{
|
||||
MemHead *memh;
|
||||
|
||||
/* on 64 bit, simply use calloc instead, as mmap does not support
|
||||
* allocating > 4 GB on Windows. the only reason mapalloc exists
|
||||
* is to get around address space limitations in 32 bit OSes. */
|
||||
if (sizeof(void *) >= 8)
|
||||
return MEM_guarded_callocN(len, str);
|
||||
|
||||
len = SIZET_ALIGN_4(len);
|
||||
|
||||
#if defined(WIN32)
|
||||
/* our windows mmap implementation is not thread safe */
|
||||
mem_lock_thread();
|
||||
#endif
|
||||
memh = mmap(NULL,
|
||||
len + sizeof(MemHead) + sizeof(MemTail),
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANON,
|
||||
-1,
|
||||
0);
|
||||
#if defined(WIN32)
|
||||
mem_unlock_thread();
|
||||
#endif
|
||||
|
||||
if (memh != (MemHead *)-1) {
|
||||
make_memhead_header(memh, len, str);
|
||||
memh->mmap = 1;
|
||||
atomic_add_and_fetch_z(&mmap_in_use, len);
|
||||
mem_lock_thread();
|
||||
peak_mem = mmap_in_use > peak_mem ? mmap_in_use : peak_mem;
|
||||
mem_unlock_thread();
|
||||
#ifdef DEBUG_MEMCOUNTER
|
||||
if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
|
||||
memcount_raise(__func__);
|
||||
memh->_count = _mallocn_count++;
|
||||
#endif
|
||||
return (++memh);
|
||||
}
|
||||
else {
|
||||
print_error(
|
||||
"Mapalloc returns null, fallback to regular malloc: "
|
||||
"len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
SIZET_ARG(len),
|
||||
str,
|
||||
(unsigned int)mmap_in_use);
|
||||
return MEM_guarded_callocN(len, str);
|
||||
}
|
||||
}
|
||||
|
||||
/* Memory statistics print */
|
||||
typedef struct MemPrintBlock {
|
||||
const char *name;
|
||||
@@ -765,7 +648,7 @@ void MEM_guarded_printmemlist_stats(void)
|
||||
pb++;
|
||||
|
||||
#ifdef USE_MALLOC_USABLE_SIZE
|
||||
if (!membl->mmap && membl->alignment == 0) {
|
||||
if (membl->alignment == 0) {
|
||||
mem_in_use_slop += (sizeof(MemHead) + sizeof(MemTail) + malloc_usable_size((void *)membl)) -
|
||||
membl->len;
|
||||
}
|
||||
@@ -1098,27 +981,13 @@ static void rem_memblock(MemHead *memh)
|
||||
free((char *)memh->name);
|
||||
#endif
|
||||
|
||||
if (memh->mmap) {
|
||||
atomic_sub_and_fetch_z(&mmap_in_use, memh->len);
|
||||
#if defined(WIN32)
|
||||
/* our windows mmap implementation is not thread safe */
|
||||
mem_lock_thread();
|
||||
#endif
|
||||
if (munmap(memh, memh->len + sizeof(MemHead) + sizeof(MemTail)))
|
||||
printf("Couldn't unmap memory %s\n", memh->name);
|
||||
#if defined(WIN32)
|
||||
mem_unlock_thread();
|
||||
#endif
|
||||
if (UNLIKELY(malloc_debug_memset && memh->len))
|
||||
memset(memh + 1, 255, memh->len);
|
||||
if (LIKELY(memh->alignment == 0)) {
|
||||
free(memh);
|
||||
}
|
||||
else {
|
||||
if (UNLIKELY(malloc_debug_memset && memh->len))
|
||||
memset(memh + 1, 255, memh->len);
|
||||
if (LIKELY(memh->alignment == 0)) {
|
||||
free(memh);
|
||||
}
|
||||
else {
|
||||
aligned_free(MEMHEAD_REAL_PTR(memh));
|
||||
}
|
||||
aligned_free(MEMHEAD_REAL_PTR(memh));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1270,17 +1139,6 @@ size_t MEM_guarded_get_memory_in_use(void)
|
||||
return _mem_in_use;
|
||||
}
|
||||
|
||||
size_t MEM_guarded_get_mapped_memory_in_use(void)
|
||||
{
|
||||
size_t _mmap_in_use;
|
||||
|
||||
mem_lock_thread();
|
||||
_mmap_in_use = mmap_in_use;
|
||||
mem_unlock_thread();
|
||||
|
||||
return _mmap_in_use;
|
||||
}
|
||||
|
||||
unsigned int MEM_guarded_get_memory_blocks_in_use(void)
|
||||
{
|
||||
unsigned int _totblock;
|
||||
|
@@ -24,13 +24,6 @@
|
||||
#ifndef __MALLOCN_INTERN_H__
|
||||
#define __MALLOCN_INTERN_H__
|
||||
|
||||
/* mmap exception */
|
||||
#if defined(WIN32)
|
||||
# include "mmap_win.h"
|
||||
#else
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define UNUSED(x) UNUSED_##x __attribute__((__unused__))
|
||||
#else
|
||||
@@ -140,19 +133,14 @@ void *MEM_lockfree_mallocN_aligned(size_t len,
|
||||
size_t alignment,
|
||||
const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
void *MEM_lockfree_mapallocN(size_t len,
|
||||
const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
|
||||
void MEM_lockfree_printmemlist_pydict(void);
|
||||
void MEM_lockfree_printmemlist(void);
|
||||
void MEM_lockfree_callbackmemlist(void (*func)(void *));
|
||||
void MEM_lockfree_printmemlist_stats(void);
|
||||
void MEM_lockfree_set_error_callback(void (*func)(const char *));
|
||||
bool MEM_lockfree_consistency_check(void);
|
||||
void MEM_lockfree_set_lock_callback(void (*lock)(void), void (*unlock)(void));
|
||||
void MEM_lockfree_set_memory_debug(void);
|
||||
size_t MEM_lockfree_get_memory_in_use(void);
|
||||
size_t MEM_lockfree_get_mapped_memory_in_use(void);
|
||||
unsigned int MEM_lockfree_get_memory_blocks_in_use(void);
|
||||
void MEM_lockfree_reset_peak_memory(void);
|
||||
size_t MEM_lockfree_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
|
||||
@@ -188,19 +176,14 @@ void *MEM_guarded_mallocN_aligned(size_t len,
|
||||
size_t alignment,
|
||||
const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(3);
|
||||
void *MEM_guarded_mapallocN(size_t len,
|
||||
const char *UNUSED(str)) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
|
||||
ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2);
|
||||
void MEM_guarded_printmemlist_pydict(void);
|
||||
void MEM_guarded_printmemlist(void);
|
||||
void MEM_guarded_callbackmemlist(void (*func)(void *));
|
||||
void MEM_guarded_printmemlist_stats(void);
|
||||
void MEM_guarded_set_error_callback(void (*func)(const char *));
|
||||
bool MEM_guarded_consistency_check(void);
|
||||
void MEM_guarded_set_lock_callback(void (*lock)(void), void (*unlock)(void));
|
||||
void MEM_guarded_set_memory_debug(void);
|
||||
size_t MEM_guarded_get_memory_in_use(void);
|
||||
size_t MEM_guarded_get_mapped_memory_in_use(void);
|
||||
unsigned int MEM_guarded_get_memory_blocks_in_use(void);
|
||||
void MEM_guarded_reset_peak_memory(void);
|
||||
size_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
|
||||
|
@@ -44,22 +44,18 @@ typedef struct MemHeadAligned {
|
||||
} MemHeadAligned;
|
||||
|
||||
static unsigned int totblock = 0;
|
||||
static size_t mem_in_use = 0, mmap_in_use = 0, peak_mem = 0;
|
||||
static size_t mem_in_use = 0, peak_mem = 0;
|
||||
static bool malloc_debug_memset = false;
|
||||
|
||||
static void (*error_callback)(const char *) = NULL;
|
||||
static void (*thread_lock_callback)(void) = NULL;
|
||||
static void (*thread_unlock_callback)(void) = NULL;
|
||||
|
||||
enum {
|
||||
MEMHEAD_MMAP_FLAG = 1,
|
||||
MEMHEAD_ALIGN_FLAG = 2,
|
||||
MEMHEAD_ALIGN_FLAG = 1,
|
||||
};
|
||||
|
||||
#define MEMHEAD_FROM_PTR(ptr) (((MemHead *)ptr) - 1)
|
||||
#define PTR_FROM_MEMHEAD(memhead) (memhead + 1)
|
||||
#define MEMHEAD_ALIGNED_FROM_PTR(ptr) (((MemHeadAligned *)ptr) - 1)
|
||||
#define MEMHEAD_IS_MMAP(memhead) ((memhead)->len & (size_t)MEMHEAD_MMAP_FLAG)
|
||||
#define MEMHEAD_IS_ALIGNED(memhead) ((memhead)->len & (size_t)MEMHEAD_ALIGN_FLAG)
|
||||
|
||||
/* Uncomment this to have proper peak counter. */
|
||||
@@ -93,24 +89,10 @@ print_error(const char *str, ...)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
static void mem_lock_thread(void)
|
||||
{
|
||||
if (thread_lock_callback)
|
||||
thread_lock_callback();
|
||||
}
|
||||
|
||||
static void mem_unlock_thread(void)
|
||||
{
|
||||
if (thread_unlock_callback)
|
||||
thread_unlock_callback();
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t MEM_lockfree_allocN_len(const void *vmemh)
|
||||
{
|
||||
if (vmemh) {
|
||||
return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_MMAP_FLAG | MEMHEAD_ALIGN_FLAG));
|
||||
return MEMHEAD_FROM_PTR(vmemh)->len & ~((size_t)(MEMHEAD_ALIGN_FLAG));
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
@@ -133,29 +115,15 @@ void MEM_lockfree_freeN(void *vmemh)
|
||||
atomic_sub_and_fetch_u(&totblock, 1);
|
||||
atomic_sub_and_fetch_z(&mem_in_use, len);
|
||||
|
||||
if (MEMHEAD_IS_MMAP(memh)) {
|
||||
atomic_sub_and_fetch_z(&mmap_in_use, len);
|
||||
#if defined(WIN32)
|
||||
/* our windows mmap implementation is not thread safe */
|
||||
mem_lock_thread();
|
||||
#endif
|
||||
if (munmap(memh, len + sizeof(MemHead)))
|
||||
printf("Couldn't unmap memory\n");
|
||||
#if defined(WIN32)
|
||||
mem_unlock_thread();
|
||||
#endif
|
||||
if (UNLIKELY(malloc_debug_memset && len)) {
|
||||
memset(memh + 1, 255, len);
|
||||
}
|
||||
if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
aligned_free(MEMHEAD_REAL_PTR(memh_aligned));
|
||||
}
|
||||
else {
|
||||
if (UNLIKELY(malloc_debug_memset && len)) {
|
||||
memset(memh + 1, 255, len);
|
||||
}
|
||||
if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
aligned_free(MEMHEAD_REAL_PTR(memh_aligned));
|
||||
}
|
||||
else {
|
||||
free(memh);
|
||||
}
|
||||
free(memh);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,10 +133,7 @@ void *MEM_lockfree_dupallocN(const void *vmemh)
|
||||
if (vmemh) {
|
||||
MemHead *memh = MEMHEAD_FROM_PTR(vmemh);
|
||||
const size_t prev_size = MEM_lockfree_allocN_len(vmemh);
|
||||
if (UNLIKELY(MEMHEAD_IS_MMAP(memh))) {
|
||||
newp = MEM_lockfree_mapallocN(prev_size, "dupli_mapalloc");
|
||||
}
|
||||
else if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
|
||||
if (UNLIKELY(MEMHEAD_IS_ALIGNED(memh))) {
|
||||
MemHeadAligned *memh_aligned = MEMHEAD_ALIGNED_FROM_PTR(vmemh);
|
||||
newp = MEM_lockfree_mallocN_aligned(
|
||||
prev_size, (size_t)memh_aligned->alignment, "dupli_malloc");
|
||||
@@ -397,47 +362,6 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *MEM_lockfree_mapallocN(size_t len, const char *str)
|
||||
{
|
||||
MemHead *memh;
|
||||
|
||||
/* on 64 bit, simply use calloc instead, as mmap does not support
|
||||
* allocating > 4 GB on Windows. the only reason mapalloc exists
|
||||
* is to get around address space limitations in 32 bit OSes. */
|
||||
if (sizeof(void *) >= 8)
|
||||
return MEM_lockfree_callocN(len, str);
|
||||
|
||||
len = SIZET_ALIGN_4(len);
|
||||
|
||||
#if defined(WIN32)
|
||||
/* our windows mmap implementation is not thread safe */
|
||||
mem_lock_thread();
|
||||
#endif
|
||||
memh = mmap(NULL, len + sizeof(MemHead), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
#if defined(WIN32)
|
||||
mem_unlock_thread();
|
||||
#endif
|
||||
|
||||
if (memh != (MemHead *)-1) {
|
||||
memh->len = len | (size_t)MEMHEAD_MMAP_FLAG;
|
||||
atomic_add_and_fetch_u(&totblock, 1);
|
||||
atomic_add_and_fetch_z(&mem_in_use, len);
|
||||
atomic_add_and_fetch_z(&mmap_in_use, len);
|
||||
|
||||
update_maximum(&peak_mem, mem_in_use);
|
||||
update_maximum(&peak_mem, mmap_in_use);
|
||||
|
||||
return PTR_FROM_MEMHEAD(memh);
|
||||
}
|
||||
print_error(
|
||||
"Mapalloc returns null, fallback to regular malloc: "
|
||||
"len=" SIZET_FORMAT " in %s, total %u\n",
|
||||
SIZET_ARG(len),
|
||||
str,
|
||||
(unsigned int)mmap_in_use);
|
||||
return MEM_lockfree_callocN(len, str);
|
||||
}
|
||||
|
||||
void MEM_lockfree_printmemlist_pydict(void)
|
||||
{
|
||||
}
|
||||
@@ -476,12 +400,6 @@ bool MEM_lockfree_consistency_check(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
void MEM_lockfree_set_lock_callback(void (*lock)(void), void (*unlock)(void))
|
||||
{
|
||||
thread_lock_callback = lock;
|
||||
thread_unlock_callback = unlock;
|
||||
}
|
||||
|
||||
void MEM_lockfree_set_memory_debug(void)
|
||||
{
|
||||
malloc_debug_memset = true;
|
||||
@@ -492,11 +410,6 @@ size_t MEM_lockfree_get_memory_in_use(void)
|
||||
return mem_in_use;
|
||||
}
|
||||
|
||||
size_t MEM_lockfree_get_mapped_memory_in_use(void)
|
||||
{
|
||||
return mmap_in_use;
|
||||
}
|
||||
|
||||
unsigned int MEM_lockfree_get_memory_blocks_in_use(void)
|
||||
{
|
||||
return totblock;
|
||||
|
@@ -150,6 +150,7 @@ if(WITH_LIBMV)
|
||||
libmv/autotrack/tracks.h
|
||||
libmv/base/aligned_malloc.h
|
||||
libmv/base/id_generator.h
|
||||
libmv/base/map.h
|
||||
libmv/base/scoped_ptr.h
|
||||
libmv/base/vector.h
|
||||
libmv/base/vector_utils.h
|
||||
|
@@ -16,6 +16,7 @@ libmv/autotrack/tracks_test.cc
|
||||
libmv/base/aligned_malloc.cc
|
||||
libmv/base/aligned_malloc.h
|
||||
libmv/base/id_generator.h
|
||||
libmv/base/map.h
|
||||
libmv/base/scoped_ptr.h
|
||||
libmv/base/scoped_ptr_test.cc
|
||||
libmv/base/vector.h
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#ifndef LIBMV_AUTOTRACK_RECONSTRUCTION_H_
|
||||
#define LIBMV_AUTOTRACK_RECONSTRUCTION_H_
|
||||
|
||||
#include "libmv/base/map.h"
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
#include "libmv/simple_pipeline/camera_intrinsics.h"
|
||||
@@ -51,7 +52,7 @@ class Point {
|
||||
};
|
||||
|
||||
// A reconstruction for a set of tracks. The indexing for clip, frame, and
|
||||
// track should match that of a Tracs object, stored elsewhere.
|
||||
// track should match that of a Tracks object, stored elsewhere.
|
||||
class Reconstruction {
|
||||
public:
|
||||
// All methods copy their input reference or take ownership of the pointer.
|
||||
@@ -75,7 +76,7 @@ class Reconstruction {
|
||||
vector<CameraIntrinsics*> camera_intrinsics_;
|
||||
|
||||
// Indexed by Marker::clip then by Marker::frame.
|
||||
vector<vector<CameraPose> > camera_poses_;
|
||||
vector<map<int, CameraPose>> camera_poses_;
|
||||
|
||||
// Indexed by Marker::track.
|
||||
vector<Point> points_;
|
||||
|
34
intern/libmv/libmv/base/map.h
Normal file
34
intern/libmv/libmv/base/map.h
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2020 libmv authors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef LIBMV_BASE_MAP_H
|
||||
#define LIBMV_BASE_MAP_H
|
||||
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
||||
namespace libmv {
|
||||
|
||||
using std::map;
|
||||
using std::make_pair;
|
||||
|
||||
} // namespace libmv
|
||||
|
||||
#endif // LIBMV_BASE_MAP_H
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "ceres/ceres.h"
|
||||
#include "ceres/rotation.h"
|
||||
#include "libmv/base/map.h"
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/logging/logging.h"
|
||||
#include "libmv/multiview/fundamental.h"
|
||||
@@ -407,47 +408,39 @@ void UnpackIntrinsicsFromArray(const double intrinsics_block[OFFSET_MAX],
|
||||
// Get a vector of camera's rotations denoted by angle axis
|
||||
// conjuncted with translations into single block
|
||||
//
|
||||
// Element with index i matches to a rotation+translation for
|
||||
// Element with key i matches to a rotation+translation for
|
||||
// camera at image i.
|
||||
vector<Vec6> PackCamerasRotationAndTranslation(
|
||||
const Tracks &tracks,
|
||||
map<int, Vec6> PackCamerasRotationAndTranslation(
|
||||
const EuclideanReconstruction &reconstruction) {
|
||||
vector<Vec6> all_cameras_R_t;
|
||||
int max_image = tracks.MaxImage();
|
||||
map<int, Vec6> all_cameras_R_t;
|
||||
|
||||
all_cameras_R_t.resize(max_image + 1);
|
||||
|
||||
for (int i = 0; i <= max_image; i++) {
|
||||
const EuclideanCamera *camera = reconstruction.CameraForImage(i);
|
||||
|
||||
if (!camera) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ceres::RotationMatrixToAngleAxis(&camera->R(0, 0),
|
||||
&all_cameras_R_t[i](0));
|
||||
all_cameras_R_t[i].tail<3>() = camera->t;
|
||||
vector<EuclideanCamera> all_cameras = reconstruction.AllCameras();
|
||||
for (const EuclideanCamera& camera : all_cameras) {
|
||||
Vec6 camera_R_t;
|
||||
ceres::RotationMatrixToAngleAxis(&camera.R(0, 0), &camera_R_t(0));
|
||||
camera_R_t.tail<3>() = camera.t;
|
||||
all_cameras_R_t.insert(make_pair(camera.image, camera_R_t));
|
||||
}
|
||||
|
||||
return all_cameras_R_t;
|
||||
}
|
||||
|
||||
// Convert cameras rotations fro mangle axis back to rotation matrix.
|
||||
void UnpackCamerasRotationAndTranslation(
|
||||
const Tracks &tracks,
|
||||
const vector<Vec6> &all_cameras_R_t,
|
||||
const map<int, Vec6> &all_cameras_R_t,
|
||||
EuclideanReconstruction *reconstruction) {
|
||||
int max_image = tracks.MaxImage();
|
||||
|
||||
for (int i = 0; i <= max_image; i++) {
|
||||
EuclideanCamera *camera = reconstruction->CameraForImage(i);
|
||||
for (map<int, Vec6>::value_type image_and_camera_R_T : all_cameras_R_t) {
|
||||
const int image = image_and_camera_R_T.first;
|
||||
const Vec6& camera_R_t = image_and_camera_R_T.second;
|
||||
|
||||
EuclideanCamera *camera = reconstruction->CameraForImage(image);
|
||||
if (!camera) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ceres::AngleAxisToRotationMatrix(&all_cameras_R_t[i](0),
|
||||
&camera->R(0, 0));
|
||||
camera->t = all_cameras_R_t[i].tail<3>();
|
||||
ceres::AngleAxisToRotationMatrix(&camera_R_t(0), &camera->R(0, 0));
|
||||
camera->t = camera_R_t.tail<3>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +469,7 @@ void CRSMatrixToEigenMatrix(const ceres::CRSMatrix &crs_matrix,
|
||||
|
||||
void EuclideanBundlerPerformEvaluation(const Tracks &tracks,
|
||||
EuclideanReconstruction *reconstruction,
|
||||
vector<Vec6> *all_cameras_R_t,
|
||||
map<int, Vec6> *all_cameras_R_t,
|
||||
ceres::Problem *problem,
|
||||
BundleEvaluation *evaluation) {
|
||||
int max_track = tracks.MaxTrack();
|
||||
@@ -603,7 +596,7 @@ void AddResidualBlockToProblem(const CameraIntrinsics *invariant_intrinsics,
|
||||
// are to be totally still here.
|
||||
void EuclideanBundlePointsOnly(const CameraIntrinsics *invariant_intrinsics,
|
||||
const vector<Marker> &markers,
|
||||
vector<Vec6> &all_cameras_R_t,
|
||||
map<int, Vec6> &all_cameras_R_t,
|
||||
double intrinsics_block[OFFSET_MAX],
|
||||
EuclideanReconstruction *reconstruction) {
|
||||
ceres::Problem::Options problem_options;
|
||||
@@ -699,8 +692,8 @@ void EuclideanBundleCommonIntrinsics(
|
||||
//
|
||||
// Block for minimization has got the following structure:
|
||||
// <3 elements for angle-axis> <3 elements for translation>
|
||||
vector<Vec6> all_cameras_R_t =
|
||||
PackCamerasRotationAndTranslation(tracks, *reconstruction);
|
||||
map<int, Vec6> all_cameras_R_t =
|
||||
PackCamerasRotationAndTranslation(*reconstruction);
|
||||
|
||||
// Parameterization used to restrict camera motion for modal solvers.
|
||||
ceres::SubsetParameterization *constant_translation_parameterization = NULL;
|
||||
@@ -827,9 +820,7 @@ void EuclideanBundleCommonIntrinsics(
|
||||
LG << "Final report:\n" << summary.FullReport();
|
||||
|
||||
// Copy rotations and translations back.
|
||||
UnpackCamerasRotationAndTranslation(tracks,
|
||||
all_cameras_R_t,
|
||||
reconstruction);
|
||||
UnpackCamerasRotationAndTranslation(all_cameras_R_t, reconstruction);
|
||||
|
||||
// Copy intrinsics back.
|
||||
if (bundle_intrinsics != BUNDLE_NO_INTRINSICS)
|
||||
|
@@ -27,14 +27,14 @@ namespace libmv {
|
||||
EuclideanReconstruction::EuclideanReconstruction() {}
|
||||
EuclideanReconstruction::EuclideanReconstruction(
|
||||
const EuclideanReconstruction &other) {
|
||||
cameras_ = other.cameras_;
|
||||
image_to_cameras_map_ = other.image_to_cameras_map_;
|
||||
points_ = other.points_;
|
||||
}
|
||||
|
||||
EuclideanReconstruction &EuclideanReconstruction::operator=(
|
||||
const EuclideanReconstruction &other) {
|
||||
if (&other != this) {
|
||||
cameras_ = other.cameras_;
|
||||
image_to_cameras_map_ = other.image_to_cameras_map_;
|
||||
points_ = other.points_;
|
||||
}
|
||||
return *this;
|
||||
@@ -44,12 +44,13 @@ void EuclideanReconstruction::InsertCamera(int image,
|
||||
const Mat3 &R,
|
||||
const Vec3 &t) {
|
||||
LG << "InsertCamera " << image << ":\nR:\n"<< R << "\nt:\n" << t;
|
||||
if (image >= cameras_.size()) {
|
||||
cameras_.resize(image + 1);
|
||||
}
|
||||
cameras_[image].image = image;
|
||||
cameras_[image].R = R;
|
||||
cameras_[image].t = t;
|
||||
|
||||
EuclideanCamera camera;
|
||||
camera.image = image;
|
||||
camera.R = R;
|
||||
camera.t = t;
|
||||
|
||||
image_to_cameras_map_.insert(make_pair(image, camera));
|
||||
}
|
||||
|
||||
void EuclideanReconstruction::InsertPoint(int track, const Vec3 &X) {
|
||||
@@ -69,22 +70,18 @@ EuclideanCamera *EuclideanReconstruction::CameraForImage(int image) {
|
||||
|
||||
const EuclideanCamera *EuclideanReconstruction::CameraForImage(
|
||||
int image) const {
|
||||
if (image < 0 || image >= cameras_.size()) {
|
||||
ImageToCameraMap::const_iterator it = image_to_cameras_map_.find(image);
|
||||
if (it == image_to_cameras_map_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
const EuclideanCamera *camera = &cameras_[image];
|
||||
if (camera->image == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return camera;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
vector<EuclideanCamera> EuclideanReconstruction::AllCameras() const {
|
||||
vector<EuclideanCamera> cameras;
|
||||
for (int i = 0; i < cameras_.size(); ++i) {
|
||||
if (cameras_[i].image != -1) {
|
||||
cameras.push_back(cameras_[i]);
|
||||
}
|
||||
for (const ImageToCameraMap::value_type& image_and_camera :
|
||||
image_to_cameras_map_) {
|
||||
cameras.push_back(image_and_camera.second);
|
||||
}
|
||||
return cameras;
|
||||
}
|
||||
@@ -115,14 +112,14 @@ vector<EuclideanPoint> EuclideanReconstruction::AllPoints() const {
|
||||
return points;
|
||||
}
|
||||
|
||||
void ProjectiveReconstruction::InsertCamera(int image,
|
||||
const Mat34 &P) {
|
||||
void ProjectiveReconstruction::InsertCamera(int image, const Mat34 &P) {
|
||||
LG << "InsertCamera " << image << ":\nP:\n"<< P;
|
||||
if (image >= cameras_.size()) {
|
||||
cameras_.resize(image + 1);
|
||||
}
|
||||
cameras_[image].image = image;
|
||||
cameras_[image].P = P;
|
||||
|
||||
ProjectiveCamera camera;
|
||||
camera.image = image;
|
||||
camera.P = P;
|
||||
|
||||
image_to_cameras_map_.insert(make_pair(image, camera));
|
||||
}
|
||||
|
||||
void ProjectiveReconstruction::InsertPoint(int track, const Vec4 &X) {
|
||||
@@ -142,22 +139,18 @@ ProjectiveCamera *ProjectiveReconstruction::CameraForImage(int image) {
|
||||
|
||||
const ProjectiveCamera *ProjectiveReconstruction::CameraForImage(
|
||||
int image) const {
|
||||
if (image < 0 || image >= cameras_.size()) {
|
||||
return NULL;
|
||||
ImageToCameraMap::const_iterator it = image_to_cameras_map_.find(image);
|
||||
if (it == image_to_cameras_map_.end()) {
|
||||
return NULL;
|
||||
}
|
||||
const ProjectiveCamera *camera = &cameras_[image];
|
||||
if (camera->image == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return camera;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
vector<ProjectiveCamera> ProjectiveReconstruction::AllCameras() const {
|
||||
vector<ProjectiveCamera> cameras;
|
||||
for (int i = 0; i < cameras_.size(); ++i) {
|
||||
if (cameras_[i].image != -1) {
|
||||
cameras.push_back(cameras_[i]);
|
||||
}
|
||||
for (const ImageToCameraMap::value_type& image_and_camera :
|
||||
image_to_cameras_map_) {
|
||||
cameras.push_back(image_and_camera.second);
|
||||
}
|
||||
return cameras;
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#define LIBMV_SIMPLE_PIPELINE_RECONSTRUCTION_H_
|
||||
|
||||
#include "libmv/base/vector.h"
|
||||
#include "libmv/base/map.h"
|
||||
#include "libmv/numeric/numeric.h"
|
||||
|
||||
namespace libmv {
|
||||
@@ -120,7 +121,11 @@ class EuclideanReconstruction {
|
||||
vector<EuclideanPoint> AllPoints() const;
|
||||
|
||||
private:
|
||||
vector<EuclideanCamera> cameras_;
|
||||
// Indexed by frame number.
|
||||
typedef map<int, EuclideanCamera> ImageToCameraMap;
|
||||
ImageToCameraMap image_to_cameras_map_;
|
||||
|
||||
// Insxed by track.
|
||||
vector<EuclideanPoint> points_;
|
||||
};
|
||||
|
||||
@@ -208,7 +213,11 @@ class ProjectiveReconstruction {
|
||||
vector<ProjectivePoint> AllPoints() const;
|
||||
|
||||
private:
|
||||
vector<ProjectiveCamera> cameras_;
|
||||
// Indexed by frame number.
|
||||
typedef map<int, ProjectiveCamera> ImageToCameraMap;
|
||||
ImageToCameraMap image_to_cameras_map_;
|
||||
|
||||
// Indexed by track.
|
||||
vector<ProjectivePoint> points_;
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -60,6 +60,19 @@ struct MANTA {
|
||||
int flags;
|
||||
} Triangle;
|
||||
|
||||
// Cache helper typedefs
|
||||
typedef struct GridItem {
|
||||
void **pointer; /* Array of pointers for this grid.*/
|
||||
int type;
|
||||
int *res;
|
||||
string name;
|
||||
} GridItem;
|
||||
|
||||
typedef struct FileItem {
|
||||
string filename;
|
||||
vector<GridItem> grids;
|
||||
} FileItem;
|
||||
|
||||
// Manta step, handling everything
|
||||
void step(struct FluidModifierData *mmd, int startFrame);
|
||||
|
||||
@@ -72,6 +85,7 @@ struct MANTA {
|
||||
void initLiquid(FluidModifierData *mmd = NULL);
|
||||
void initLiquidMesh(FluidModifierData *mmd = NULL);
|
||||
void initObstacle(FluidModifierData *mmd = NULL);
|
||||
void initCurvature(FluidModifierData *mmd = NULL);
|
||||
void initGuiding(FluidModifierData *mmd = NULL);
|
||||
void initFractions(FluidModifierData *mmd = NULL);
|
||||
void initInVelocity(FluidModifierData *mmd = NULL);
|
||||
@@ -761,6 +775,7 @@ struct MANTA {
|
||||
bool mUsingOutflow;
|
||||
bool mUsingNoise;
|
||||
bool mUsingMesh;
|
||||
bool mUsingDiffusion;
|
||||
bool mUsingMVel;
|
||||
bool mUsingLiquid;
|
||||
bool mUsingSmoke;
|
||||
@@ -888,12 +903,12 @@ struct MANTA {
|
||||
bool updateMeshFromObj(string filename);
|
||||
bool updateMeshFromUni(string filename);
|
||||
bool updateParticlesFromUni(string filename, bool isSecondarySys, bool isVelData);
|
||||
bool updateGridFromUni(string filename, float *grid, bool isNoise);
|
||||
bool updateGridFromVDB(string filename, float *grid, bool isNoise);
|
||||
bool updateGridFromRaw(string filename, float *grid, bool isNoise);
|
||||
bool updateGridsFromUni(string filename, vector<GridItem> grids);
|
||||
bool updateGridsFromVDB(string filename, vector<GridItem> grids);
|
||||
bool updateGridsFromRaw(string filename, vector<GridItem> grids);
|
||||
bool updateMeshFromFile(string filename);
|
||||
bool updateParticlesFromFile(string filename, bool isSecondarySys, bool isVelData);
|
||||
bool updateGridFromFile(string filename, float *grid, bool isNoise);
|
||||
bool updateGridsFromFile(string filename, vector<GridItem> grids);
|
||||
string getDirectory(struct FluidModifierData *mmd, string subdirectory);
|
||||
string getFile(struct FluidModifierData *mmd,
|
||||
string subdirectory,
|
||||
|
@@ -259,7 +259,7 @@ const std::string fluid_alloc =
|
||||
"\n\
|
||||
mantaMsg('Fluid alloc data')\n\
|
||||
flags_s$ID$ = s$ID$.create(FlagGrid)\n\
|
||||
vel_s$ID$ = s$ID$.create(MACGrid)\n\
|
||||
vel_s$ID$ = s$ID$.create(MACGrid, name='$NAME_VELOCITY$')\n\
|
||||
velTmp_s$ID$ = s$ID$.create(MACGrid)\n\
|
||||
x_vel_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
y_vel_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
|
@@ -80,11 +80,11 @@ mantaMsg('Liquid alloc')\n\
|
||||
phiParts_s$ID$ = s$ID$.create(LevelsetGrid)\n\
|
||||
phi_s$ID$ = s$ID$.create(LevelsetGrid)\n\
|
||||
phiTmp_s$ID$ = s$ID$.create(LevelsetGrid)\n\
|
||||
curvature_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
velOld_s$ID$ = s$ID$.create(MACGrid)\n\
|
||||
velParts_s$ID$ = s$ID$.create(MACGrid)\n\
|
||||
mapWeights_s$ID$ = s$ID$.create(MACGrid)\n\
|
||||
fractions_s$ID$ = None # allocated dynamically\n\
|
||||
curvature_s$ID$ = None\n\
|
||||
\n\
|
||||
pp_s$ID$ = s$ID$.create(BasicParticleSystem)\n\
|
||||
pVel_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
|
||||
@@ -124,6 +124,11 @@ liquid_mesh_dict_s$ID$ = dict(lMesh=mesh_sm$ID$)\n\
|
||||
if using_speedvectors_s$ID$:\n\
|
||||
liquid_meshvel_dict_s$ID$ = dict(lVelMesh=mVel_mesh$ID$)\n";
|
||||
|
||||
const std::string liquid_alloc_curvature =
|
||||
"\n\
|
||||
mantaMsg('Liquid alloc curvature')\n\
|
||||
curvature_s$ID$ = s$ID$.create(RealGrid)\n";
|
||||
|
||||
const std::string liquid_alloc_particles =
|
||||
"\n\
|
||||
ppSnd_sp$ID$ = sp$ID$.create(BasicParticleSystem)\n\
|
||||
@@ -227,7 +232,7 @@ def liquid_step_$ID$():\n\
|
||||
mantaMsg('Liquid step')\n\
|
||||
\n\
|
||||
mantaMsg('Advecting particles')\n\
|
||||
pp_s$ID$.advectInGrid(flags=flags_s$ID$, vel=vel_s$ID$, integrationMode=IntRK4, deleteInObstacle=deleteInObstacle_s$ID$, stopInObstacle=False)\n\
|
||||
pp_s$ID$.advectInGrid(flags=flags_s$ID$, vel=vel_s$ID$, integrationMode=IntRK4, deleteInObstacle=deleteInObstacle_s$ID$, stopInObstacle=False, skipNew=True)\n\
|
||||
\n\
|
||||
mantaMsg('Pushing particles out of obstacles')\n\
|
||||
pushOutofObs(parts=pp_s$ID$, flags=flags_s$ID$, phiObs=phiObs_s$ID$)\n\
|
||||
@@ -284,12 +289,13 @@ def liquid_step_$ID$():\n\
|
||||
alphaV = viscosity_s$ID$ * s$ID$.timestep * float(res_s$ID$*res_s$ID$)\n\
|
||||
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
|
||||
cgSolveDiffusion(flags_s$ID$, vel_s$ID$, alphaV)\n\
|
||||
\n\
|
||||
mantaMsg('Curvature')\n\
|
||||
getLaplacian(laplacian=curvature_s$ID$, grid=phi_s$ID$)\n\
|
||||
curvature_s$ID$.clamp(-1.0, 1.0)\n\
|
||||
\n\
|
||||
setWallBcs(flags=flags_s$ID$, vel=vel_s$ID$, obvel=None if using_fractions_s$ID$ else obvel_s$ID$, phiObs=phiObs_s$ID$, fractions=fractions_s$ID$)\n\
|
||||
\n\
|
||||
mantaMsg('Calculating curvature')\n\
|
||||
getLaplacian(laplacian=curvature_s$ID$, grid=phi_s$ID$)\n\
|
||||
\n\
|
||||
if using_guiding_s$ID$:\n\
|
||||
mantaMsg('Guiding and pressure')\n\
|
||||
PD_fluid_guiding(vel=vel_s$ID$, velT=velT_s$ID$, flags=flags_s$ID$, phi=phi_s$ID$, curv=curvature_s$ID$, surfTens=surfaceTension_s$ID$, fractions=fractions_s$ID$, weight=weightGuide_s$ID$, blurRadius=beta_sg$ID$, pressure=pressure_s$ID$, tau=tau_sg$ID$, sigma=sigma_sg$ID$, theta=theta_sg$ID$, zeroPressureFixing=not doOpen_s$ID$)\n\
|
||||
@@ -343,7 +349,10 @@ def liquid_step_mesh_$ID$():\n\
|
||||
interpolateMACGrid(target=vel_sm$ID$, source=vel_s$ID$)\n\
|
||||
mVel_mesh$ID$.setSource(vel_sm$ID$, isMAC=True)\n\
|
||||
\n\
|
||||
phi_sm$ID$.setBound(0.5,int(((upres_sm$ID$)*2)-2) )\n\
|
||||
# Set 0.5 boundary at walls + account for extra wall thickness in fractions mode + account for grid scaling:\n\
|
||||
# E.g. at upres=1 we expect 1 cell border (or 2 with fractions), at upres=2 we expect 2 cell border (or 4 with fractions), etc.\n\
|
||||
# Use -1 since setBound() starts counting at 0 (and additional -1 for fractions to account for solid/fluid interface cells)\n\
|
||||
phi_sm$ID$.setBound(value=0.5, boundaryWidth=(upres_sm$ID$*2)-2 if using_fractions_s$ID$ else upres_sm$ID$-1)\n\
|
||||
phi_sm$ID$.createMesh(mesh_sm$ID$)\n";
|
||||
|
||||
const std::string liquid_step_particles =
|
||||
|
@@ -81,10 +81,10 @@ using_fire_s$ID$ = True\n";
|
||||
const std::string smoke_alloc =
|
||||
"\n\
|
||||
mantaMsg('Smoke alloc')\n\
|
||||
shadow_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
shadow_s$ID$ = s$ID$.create(RealGrid, name='$NAME_SHADOW$')\n\
|
||||
emission_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
emissionIn_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
density_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
density_s$ID$ = s$ID$.create(RealGrid, name='$NAME_DENSITY$')\n\
|
||||
densityIn_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
heat_s$ID$ = None # allocated dynamically\n\
|
||||
heatIn_s$ID$ = None\n\
|
||||
@@ -108,7 +108,7 @@ const std::string smoke_alloc_noise =
|
||||
"\n\
|
||||
mantaMsg('Smoke alloc noise')\n\
|
||||
vel_sn$ID$ = sn$ID$.create(MACGrid)\n\
|
||||
density_sn$ID$ = sn$ID$.create(RealGrid)\n\
|
||||
density_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_DENSITYNOISE$')\n\
|
||||
phiIn_sn$ID$ = sn$ID$.create(LevelsetGrid)\n\
|
||||
phiOut_sn$ID$ = sn$ID$.create(LevelsetGrid)\n\
|
||||
phiObs_sn$ID$ = sn$ID$.create(LevelsetGrid)\n\
|
||||
@@ -157,9 +157,9 @@ if 'color_g_s$ID$' in globals(): del color_g_s$ID$\n\
|
||||
if 'color_b_s$ID$' in globals(): del color_b_s$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating colors')\n\
|
||||
color_r_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
color_g_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
color_b_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
color_r_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORR$')\n\
|
||||
color_g_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORG$')\n\
|
||||
color_b_s$ID$ = s$ID$.create(RealGrid, name='$NAME_COLORB$')\n\
|
||||
color_r_in_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
color_g_in_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
color_b_in_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
@@ -178,9 +178,9 @@ if 'color_g_sn$ID$' in globals(): del color_g_sn$ID$\n\
|
||||
if 'color_b_sn$ID$' in globals(): del color_b_sn$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating colors noise')\n\
|
||||
color_r_sn$ID$ = sn$ID$.create(RealGrid)\n\
|
||||
color_g_sn$ID$ = sn$ID$.create(RealGrid)\n\
|
||||
color_b_sn$ID$ = sn$ID$.create(RealGrid)\n\
|
||||
color_r_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORRNOISE$')\n\
|
||||
color_g_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORGNOISE$')\n\
|
||||
color_b_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_COLORBNOISE$')\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
|
||||
@@ -213,7 +213,7 @@ if 'heat_s$ID$' in globals(): del heat_s$ID$\n\
|
||||
if 'heatIn_s$ID$' in globals(): del heatIn_s$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating heat')\n\
|
||||
heat_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
heat_s$ID$ = s$ID$.create(RealGrid, name='$NAME_HEAT$')\n\
|
||||
heatIn_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
@@ -232,9 +232,9 @@ if 'fuelIn_s$ID$' in globals(): del fuelIn_s$ID$\n\
|
||||
if 'reactIn_s$ID$' in globals(): del reactIn_s$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating fire')\n\
|
||||
flame_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
fuel_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
react_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
flame_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FLAME$')\n\
|
||||
fuel_s$ID$ = s$ID$.create(RealGrid, name='$NAME_FUEL$')\n\
|
||||
react_s$ID$ = s$ID$.create(RealGrid, name='$NAME_REACT$')\n\
|
||||
fuelIn_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
reactIn_s$ID$ = s$ID$.create(RealGrid)\n\
|
||||
\n\
|
||||
@@ -252,9 +252,9 @@ if 'fuel_sn$ID$' in globals(): del fuel_sn$ID$\n\
|
||||
if 'react_sn$ID$' in globals(): del react_sn$ID$\n\
|
||||
\n\
|
||||
mantaMsg('Allocating fire noise')\n\
|
||||
flame_sn$ID$ = sn$ID$.create(RealGrid)\n\
|
||||
fuel_sn$ID$ = sn$ID$.create(RealGrid)\n\
|
||||
react_sn$ID$ = sn$ID$.create(RealGrid)\n\
|
||||
flame_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FLAMENOISE$')\n\
|
||||
fuel_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_FUELNOISE$')\n\
|
||||
react_sn$ID$ = sn$ID$.create(RealGrid, name='$NAME_REACTNOISE$')\n\
|
||||
\n\
|
||||
# Add objects to dict to load them later on\n\
|
||||
if 'smoke_noise_dict_final_s$ID$' in globals():\n\
|
||||
|
@@ -31,7 +31,6 @@ set(SRC
|
||||
opensubdiv_capi_type.h
|
||||
opensubdiv_converter_capi.h
|
||||
opensubdiv_evaluator_capi.h
|
||||
opensubdiv_gl_mesh_capi.h
|
||||
opensubdiv_topology_refiner_capi.h
|
||||
)
|
||||
|
||||
@@ -54,30 +53,20 @@ if(WITH_OPENSUBDIV)
|
||||
internal/opensubdiv.cc
|
||||
internal/opensubdiv_converter_factory.cc
|
||||
internal/opensubdiv_converter_internal.cc
|
||||
internal/opensubdiv_converter_orient.cc
|
||||
internal/opensubdiv_device_context_cuda.cc
|
||||
internal/opensubdiv_device_context_opencl.cc
|
||||
internal/opensubdiv_evaluator.cc
|
||||
internal/opensubdiv_evaluator_internal.cc
|
||||
internal/opensubdiv_gl_mesh.cc
|
||||
internal/opensubdiv_gl_mesh_draw.cc
|
||||
internal/opensubdiv_gl_mesh_fvar.cc
|
||||
internal/opensubdiv_gl_mesh_internal.cc
|
||||
internal/opensubdiv_topology_refiner.cc
|
||||
internal/opensubdiv_topology_refiner_internal.cc
|
||||
internal/opensubdiv_util.cc
|
||||
|
||||
internal/opensubdiv_converter_factory.h
|
||||
internal/opensubdiv_converter_internal.h
|
||||
internal/opensubdiv_converter_orient.h
|
||||
internal/opensubdiv_converter_orient_impl.h
|
||||
internal/opensubdiv_device_context_cuda.h
|
||||
internal/opensubdiv_device_context_opencl.h
|
||||
internal/opensubdiv_edge_map.h
|
||||
internal/opensubdiv_evaluator_internal.h
|
||||
internal/opensubdiv_gl_mesh_draw.h
|
||||
internal/opensubdiv_gl_mesh_fvar.h
|
||||
internal/opensubdiv_gl_mesh_internal.h
|
||||
internal/opensubdiv_internal.h
|
||||
internal/opensubdiv_topology_refiner_internal.h
|
||||
internal/opensubdiv_util.h
|
||||
@@ -101,11 +90,7 @@ if(WITH_OPENSUBDIV)
|
||||
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK)
|
||||
OPENSUBDIV_DEFINE_COMPONENT(OPENSUBDIV_HAS_GLSL_COMPUTE)
|
||||
|
||||
data_to_c_simple(shader/gpu_shader_opensubdiv_vertex.glsl SRC)
|
||||
data_to_c_simple(shader/gpu_shader_opensubdiv_geometry.glsl SRC)
|
||||
data_to_c_simple(shader/gpu_shader_opensubdiv_fragment.glsl SRC)
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
add_definitions(${GL_DEFINITIONS})
|
||||
add_definitions(-DOSD_USES_GLEW)
|
||||
|
||||
if(WIN32)
|
||||
@@ -131,7 +116,6 @@ else()
|
||||
list(APPEND SRC
|
||||
stub/opensubdiv_stub.cc
|
||||
stub/opensubdiv_evaluator_stub.cc
|
||||
stub/opensubdiv_gl_mesh_stub.cc
|
||||
stub/opensubdiv_topology_refiner_stub.cc
|
||||
)
|
||||
endif()
|
||||
|
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "opensubdiv_device_context_cuda.h"
|
||||
#include "opensubdiv_device_context_opencl.h"
|
||||
#include "opensubdiv_gl_mesh_capi.h"
|
||||
|
||||
void openSubdiv_init(void)
|
||||
{
|
||||
@@ -34,7 +33,6 @@ void openSubdiv_init(void)
|
||||
|
||||
void openSubdiv_cleanup(void)
|
||||
{
|
||||
openSubdiv_deinitGLMeshDrawingResources();
|
||||
}
|
||||
|
||||
int openSubdiv_getAvailableEvaluators(void)
|
||||
@@ -86,7 +84,7 @@ int openSubdiv_getVersionHex(void)
|
||||
}
|
||||
int major = 0, minor = 0, patch = 0;
|
||||
vector<string> tokens;
|
||||
opensubdiv_capi::stringSplit(&tokens, version, "_", true);
|
||||
blender::opensubdiv::stringSplit(&tokens, version, "_", true);
|
||||
if (tokens.size() == 3) {
|
||||
major = atoi(tokens[0].c_str());
|
||||
minor = atoi(tokens[1].c_str());
|
||||
|
@@ -28,14 +28,13 @@
|
||||
#include <opensubdiv/far/topologyRefinerFactory.h>
|
||||
|
||||
#include "internal/opensubdiv_converter_internal.h"
|
||||
#include "internal/opensubdiv_converter_orient.h"
|
||||
#include "internal/opensubdiv_internal.h"
|
||||
#include "internal/opensubdiv_util.h"
|
||||
#include "opensubdiv_converter_capi.h"
|
||||
|
||||
using opensubdiv_capi::min;
|
||||
using opensubdiv_capi::stack;
|
||||
using opensubdiv_capi::vector;
|
||||
using blender::opensubdiv::min;
|
||||
using blender::opensubdiv::stack;
|
||||
using blender::opensubdiv::vector;
|
||||
|
||||
struct TopologyRefinerData {
|
||||
const OpenSubdiv_Converter *converter;
|
||||
@@ -246,7 +245,8 @@ inline void TopologyRefinerFactory<TopologyRefinerData>::reportInvalidTopology(
|
||||
} /* namespace OPENSUBDIV_VERSION */
|
||||
} /* namespace OpenSubdiv */
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -292,4 +292,5 @@ OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter(
|
||||
return TopologyRefinerFactory<TopologyRefinerData>::Create(cb_data, topology_options);
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
@@ -27,11 +27,13 @@
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
OpenSubdiv::Far::TopologyRefiner *createOSDTopologyRefinerFromConverter(
|
||||
struct OpenSubdiv_Converter *converter);
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
||||
#endif // OPENSUBDIV_CONVERTER_FACTORY_H_
|
||||
|
@@ -25,7 +25,8 @@
|
||||
#include <cassert>
|
||||
#include <opensubdiv/sdc/crease.h>
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
OpenSubdiv::Sdc::SchemeType getSchemeTypeFromCAPI(OpenSubdiv_SchemeType type)
|
||||
{
|
||||
@@ -85,4 +86,5 @@ OpenSubdiv_FVarLinearInterpolation getCAPIFVarLinearInterpolationFromOSD(
|
||||
return OSD_FVAR_LINEAR_INTERPOLATION_NONE;
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
@@ -30,7 +30,8 @@
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
// Convert scheme type from C-API enum to an OpenSubdiv native enum.
|
||||
OpenSubdiv::Sdc::SchemeType getSchemeTypeFromCAPI(OpenSubdiv_SchemeType type);
|
||||
@@ -44,6 +45,7 @@ OpenSubdiv::Sdc::Options::FVarLinearInterpolation getFVarLinearInterpolationFrom
|
||||
OpenSubdiv_FVarLinearInterpolation getCAPIFVarLinearInterpolationFromOSD(
|
||||
OpenSubdiv::Sdc::Options::FVarLinearInterpolation linear_interpolation);
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
||||
#endif // OPENSUBDIV_CONVERTER_INTERNAL_H_
|
||||
|
@@ -1,67 +0,0 @@
|
||||
// Copyright 2018 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// Author: Sergey Sharybin
|
||||
|
||||
#include "internal/opensubdiv_converter_orient.h"
|
||||
|
||||
#include "internal/opensubdiv_internal.h"
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
|
||||
void checkOrientedVertexConnectivity(const int num_vertex_edges,
|
||||
const int num_vertex_faces,
|
||||
const int *vertex_edges,
|
||||
const int *vertex_faces,
|
||||
const int *dst_vertex_edges,
|
||||
const int *dst_vertex_faces)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
for (int i = 0; i < num_vertex_faces; ++i) {
|
||||
bool found = false;
|
||||
for (int j = 0; j < num_vertex_faces; ++j) {
|
||||
if (vertex_faces[i] == dst_vertex_faces[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(!"vert-faces connectivity ruined");
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < num_vertex_edges; ++i) {
|
||||
bool found = false;
|
||||
for (int j = 0; j < num_vertex_edges; ++j) {
|
||||
if (vertex_edges[i] == dst_vertex_edges[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(!"vert-edges connectivity ruined");
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)num_vertex_edges;
|
||||
(void)num_vertex_faces;
|
||||
(void)vertex_edges;
|
||||
(void)vertex_faces;
|
||||
(void)dst_vertex_edges;
|
||||
(void)dst_vertex_faces;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
@@ -1,49 +0,0 @@
|
||||
// Copyright 2018 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// Author: Sergey Sharybin
|
||||
|
||||
#ifndef OPENSUBDIV_CONVERTER_ORIENT_H_
|
||||
# define OPENSUBDIV_CONVERTER_ORIENT_H_
|
||||
|
||||
# include <opensubdiv/far/types.h>
|
||||
|
||||
// Set of utility functions which are needed to bring topology to an orientation
|
||||
// (or, winding, if you wish) which OpenSubdiv expects.
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
|
||||
inline void reverseFaceVertices(int *face_vertices, const int num_vertices);
|
||||
|
||||
// TODO(sergey): Document which value corresponds to which winding.
|
||||
inline int getLoopWinding(int vert0_of_face, int vert1_of_face);
|
||||
|
||||
inline void reverseFaceLoops(OpenSubdiv::Far::IndexArray *face_vertices,
|
||||
OpenSubdiv::Far::IndexArray *face_edges);
|
||||
|
||||
// Used for debugging, checks whether orientation happened correct.
|
||||
void checkOrientedVertexConnectivity(const int num_vertex_edges,
|
||||
const int num_vertex_faces,
|
||||
const int *vertex_edges,
|
||||
const int *vertex_faces,
|
||||
const int *dst_vertex_edges,
|
||||
const int *dst_vertex_faces);
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
|
||||
#endif // OPENSUBDIV_CONVERTER_ORIENT_H_
|
||||
|
||||
#include "internal/opensubdiv_converter_orient_impl.h"
|
@@ -1,69 +0,0 @@
|
||||
// Copyright 2018 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// Author: Sergey Sharybin
|
||||
|
||||
#ifndef OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
|
||||
#define OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
|
||||
|
||||
#include "internal/opensubdiv_converter_orient.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "internal/opensubdiv_util.h"
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
|
||||
inline void reverseFaceVertices(int *face_vertices, const int num_vertices)
|
||||
{
|
||||
int last_vert = face_vertices[num_vertices - 1];
|
||||
for (int i = num_vertices - 1; i > 0; --i) {
|
||||
face_vertices[i] = face_vertices[i - 1];
|
||||
}
|
||||
face_vertices[0] = last_vert;
|
||||
}
|
||||
|
||||
inline int getLoopWinding(int vert0_of_face, int vert1_of_face)
|
||||
{
|
||||
int delta_face = vert1_of_face - vert0_of_face;
|
||||
if (abs(delta_face) != 1) {
|
||||
if (delta_face > 0) {
|
||||
delta_face = -1;
|
||||
}
|
||||
else {
|
||||
delta_face = 1;
|
||||
}
|
||||
}
|
||||
return delta_face;
|
||||
}
|
||||
|
||||
inline void reverseFaceLoops(OpenSubdiv::Far::IndexArray *face_vertices,
|
||||
OpenSubdiv::Far::IndexArray *face_edges)
|
||||
{
|
||||
const int num_face_vertices = face_vertices->size();
|
||||
for (int i = 0; i < num_face_vertices / 2; ++i) {
|
||||
const int j = num_face_vertices - i - 1;
|
||||
if (i != j) {
|
||||
swap((*face_vertices)[i], (*face_vertices)[j]);
|
||||
swap((*face_edges)[i], (*face_edges)[j]);
|
||||
}
|
||||
}
|
||||
reverseFaceVertices(&(*face_vertices)[0], num_face_vertices);
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
|
||||
#endif // OPENSUBDIV_CONVERTER_ORIENT_IMPL_H_
|
@@ -21,7 +21,8 @@
|
||||
|
||||
#include "internal/opensubdiv_util.h"
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
// Helper class to ease dealing with edge indexing.
|
||||
// Simply takes care of ensuring order of vertices is strictly defined.
|
||||
@@ -144,12 +145,13 @@ template<typename T> typename EdgeTagMap<T>::value_type &EdgeTagMap<T>::operator
|
||||
return edge_tags_[key];
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
||||
namespace std {
|
||||
|
||||
template<> struct hash<opensubdiv_capi::EdgeKey> {
|
||||
std::size_t operator()(const opensubdiv_capi::EdgeKey &key) const
|
||||
template<> struct hash<blender::opensubdiv::EdgeKey> {
|
||||
std::size_t operator()(const blender::opensubdiv::EdgeKey &key) const
|
||||
{
|
||||
return key.hash();
|
||||
}
|
||||
|
@@ -53,7 +53,8 @@ using OpenSubdiv::Osd::CpuPatchTable;
|
||||
using OpenSubdiv::Osd::CpuVertexBuffer;
|
||||
using OpenSubdiv::Osd::PatchCoord;
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -731,7 +732,8 @@ void CpuEvalOutputAPI::evaluatePatchesLimit(const OpenSubdiv_PatchCoord *patch_c
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
||||
OpenSubdiv_EvaluatorInternal::OpenSubdiv_EvaluatorInternal()
|
||||
: eval_output(NULL), patch_map(NULL), patch_table(NULL)
|
||||
@@ -748,7 +750,7 @@ OpenSubdiv_EvaluatorInternal::~OpenSubdiv_EvaluatorInternal()
|
||||
OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner)
|
||||
{
|
||||
using opensubdiv_capi::vector;
|
||||
using blender::opensubdiv::vector;
|
||||
TopologyRefiner *refiner = topology_refiner->internal->osd_topology_refiner;
|
||||
if (refiner == NULL) {
|
||||
// Happens on bad topology.
|
||||
@@ -851,13 +853,13 @@ OpenSubdiv_EvaluatorInternal *openSubdiv_createEvaluatorInternal(
|
||||
}
|
||||
// Create OpenSubdiv's CPU side evaluator.
|
||||
// TODO(sergey): Make it possible to use different evaluators.
|
||||
opensubdiv_capi::CpuEvalOutput *eval_output = new opensubdiv_capi::CpuEvalOutput(
|
||||
blender::opensubdiv::CpuEvalOutput *eval_output = new blender::opensubdiv::CpuEvalOutput(
|
||||
vertex_stencils, varying_stencils, all_face_varying_stencils, 2, patch_table);
|
||||
OpenSubdiv::Far::PatchMap *patch_map = new PatchMap(*patch_table);
|
||||
// Wrap everything we need into an object which we control from our side.
|
||||
OpenSubdiv_EvaluatorInternal *evaluator_descr;
|
||||
evaluator_descr = OBJECT_GUARDED_NEW(OpenSubdiv_EvaluatorInternal);
|
||||
evaluator_descr->eval_output = new opensubdiv_capi::CpuEvalOutputAPI(eval_output, patch_map);
|
||||
evaluator_descr->eval_output = new blender::opensubdiv::CpuEvalOutputAPI(eval_output, patch_map);
|
||||
evaluator_descr->patch_map = patch_map;
|
||||
evaluator_descr->patch_table = patch_table;
|
||||
// TOOD(sergey): Look into whether we've got duplicated stencils arrays.
|
||||
|
@@ -29,7 +29,8 @@
|
||||
struct OpenSubdiv_PatchCoord;
|
||||
struct OpenSubdiv_TopologyRefiner;
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
||||
// Anonymous forward declaration of actual evaluator implementation.
|
||||
class CpuEvalOutput;
|
||||
@@ -132,14 +133,15 @@ class CpuEvalOutputAPI {
|
||||
OpenSubdiv::Far::PatchMap *patch_map_;
|
||||
};
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
} // namespace opensubdiv
|
||||
} // namespace blender
|
||||
|
||||
struct OpenSubdiv_EvaluatorInternal {
|
||||
public:
|
||||
OpenSubdiv_EvaluatorInternal();
|
||||
~OpenSubdiv_EvaluatorInternal();
|
||||
|
||||
opensubdiv_capi::CpuEvalOutputAPI *eval_output;
|
||||
blender::opensubdiv::CpuEvalOutputAPI *eval_output;
|
||||
const OpenSubdiv::Far::PatchMap *patch_map;
|
||||
const OpenSubdiv::Far::PatchTable *patch_table;
|
||||
};
|
||||
|
@@ -1,260 +0,0 @@
|
||||
// Copyright 2013 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "opensubdiv_gl_mesh_capi.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <iso646.h>
|
||||
#endif
|
||||
|
||||
#include <opensubdiv/far/stencilTable.h>
|
||||
#include <opensubdiv/osd/glMesh.h>
|
||||
#include <opensubdiv/osd/glPatchTable.h>
|
||||
|
||||
using OpenSubdiv::Far::StencilTable;
|
||||
using OpenSubdiv::Osd::GLMeshInterface;
|
||||
using OpenSubdiv::Osd::GLPatchTable;
|
||||
using OpenSubdiv::Osd::Mesh;
|
||||
using OpenSubdiv::Osd::MeshBitset;
|
||||
|
||||
// CPU backend.
|
||||
#include <opensubdiv/osd/cpuEvaluator.h>
|
||||
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
|
||||
using OpenSubdiv::Osd::CpuEvaluator;
|
||||
using OpenSubdiv::Osd::CpuGLVertexBuffer;
|
||||
typedef Mesh<CpuGLVertexBuffer, StencilTable, CpuEvaluator, GLPatchTable> OsdCpuMesh;
|
||||
// OpenMP backend.
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
# include <opensubdiv/osd/ompEvaluator.h>
|
||||
using OpenSubdiv::Osd::OmpEvaluator;
|
||||
typedef Mesh<CpuGLVertexBuffer, StencilTable, OmpEvaluator, GLPatchTable> OsdOmpMesh;
|
||||
#endif
|
||||
// OpenCL backend.
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
# include "opensubdiv_device_context_opencl.h"
|
||||
# include <opensubdiv/osd/clEvaluator.h>
|
||||
# include <opensubdiv/osd/clGLVertexBuffer.h>
|
||||
using OpenSubdiv::Osd::CLEvaluator;
|
||||
using OpenSubdiv::Osd::CLGLVertexBuffer;
|
||||
using OpenSubdiv::Osd::CLStencilTable;
|
||||
/* TODO(sergey): Use CLDeviceContext similar to OSD examples? */
|
||||
typedef Mesh<CLGLVertexBuffer, CLStencilTable, CLEvaluator, GLPatchTable, CLDeviceContext>
|
||||
OsdCLMesh;
|
||||
static CLDeviceContext g_cl_device_context;
|
||||
#endif
|
||||
// CUDA backend.
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
# include "opensubdiv_device_context_cuda.h"
|
||||
# include <opensubdiv/osd/cudaEvaluator.h>
|
||||
# include <opensubdiv/osd/cudaGLVertexBuffer.h>
|
||||
using OpenSubdiv::Osd::CudaEvaluator;
|
||||
using OpenSubdiv::Osd::CudaGLVertexBuffer;
|
||||
using OpenSubdiv::Osd::CudaStencilTable;
|
||||
typedef Mesh<CudaGLVertexBuffer, CudaStencilTable, CudaEvaluator, GLPatchTable> OsdCudaMesh;
|
||||
static CudaDeviceContext g_cuda_device_context;
|
||||
#endif
|
||||
// Transform feedback backend.
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
# include <opensubdiv/osd/glVertexBuffer.h>
|
||||
# include <opensubdiv/osd/glXFBEvaluator.h>
|
||||
using OpenSubdiv::Osd::GLStencilTableTBO;
|
||||
using OpenSubdiv::Osd::GLVertexBuffer;
|
||||
using OpenSubdiv::Osd::GLXFBEvaluator;
|
||||
typedef Mesh<GLVertexBuffer, GLStencilTableTBO, GLXFBEvaluator, GLPatchTable>
|
||||
OsdGLSLTransformFeedbackMesh;
|
||||
#endif
|
||||
// GLSL compute backend.
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
# include <opensubdiv/osd/glComputeEvaluator.h>
|
||||
# include <opensubdiv/osd/glVertexBuffer.h>
|
||||
using OpenSubdiv::Osd::GLComputeEvaluator;
|
||||
using OpenSubdiv::Osd::GLStencilTableSSBO;
|
||||
using OpenSubdiv::Osd::GLVertexBuffer;
|
||||
typedef Mesh<GLVertexBuffer, GLStencilTableSSBO, GLComputeEvaluator, GLPatchTable>
|
||||
OsdGLSLComputeMesh;
|
||||
#endif
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "internal/opensubdiv_gl_mesh_draw.h"
|
||||
#include "internal/opensubdiv_gl_mesh_fvar.h"
|
||||
#include "internal/opensubdiv_gl_mesh_internal.h"
|
||||
#include "internal/opensubdiv_topology_refiner_internal.h"
|
||||
#include "internal/opensubdiv_util.h"
|
||||
#include "opensubdiv_topology_refiner_capi.h"
|
||||
|
||||
using opensubdiv_capi::vector;
|
||||
|
||||
namespace {
|
||||
|
||||
GLMeshInterface *createGLMeshInterface(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
|
||||
const MeshBitset &bits,
|
||||
const int num_vertex_elements,
|
||||
const int num_varying_elements,
|
||||
const int level,
|
||||
eOpenSubdivEvaluator evaluator_type)
|
||||
{
|
||||
GLMeshInterface *mesh = NULL;
|
||||
switch (evaluator_type) {
|
||||
#define CHECK_EVALUATOR_TYPE(type, class) \
|
||||
case OPENSUBDIV_EVALUATOR_##type: \
|
||||
mesh = new class(topology_refiner, num_vertex_elements, num_varying_elements, level, bits); \
|
||||
break;
|
||||
|
||||
#define CHECK_EVALUATOR_TYPE_STUB(type) \
|
||||
case OPENSUBDIV_EVALUATOR_##type: \
|
||||
mesh = NULL; \
|
||||
break;
|
||||
|
||||
CHECK_EVALUATOR_TYPE(CPU, OsdCpuMesh)
|
||||
#ifdef OPENSUBDIV_HAS_OPENMP
|
||||
CHECK_EVALUATOR_TYPE(OPENMP, OsdOmpMesh)
|
||||
#else
|
||||
CHECK_EVALUATOR_TYPE_STUB(OPENMP)
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_OPENCL
|
||||
CHECK_EVALUATOR_TYPE(OPENCL, OsdCLMesh)
|
||||
#else
|
||||
CHECK_EVALUATOR_TYPE_STUB(OPENCL)
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
CHECK_EVALUATOR_TYPE(CUDA, OsdCudaMesh)
|
||||
#else
|
||||
CHECK_EVALUATOR_TYPE_STUB(CUDA)
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
||||
CHECK_EVALUATOR_TYPE(GLSL_TRANSFORM_FEEDBACK, OsdGLSLTransformFeedbackMesh)
|
||||
#else
|
||||
CHECK_EVALUATOR_TYPE_STUB(GLSL_TRANSFORM_FEEDBACK)
|
||||
#endif
|
||||
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
||||
CHECK_EVALUATOR_TYPE(GLSL_COMPUTE, OsdGLSLComputeMesh)
|
||||
#else
|
||||
CHECK_EVALUATOR_TYPE_STUB(GLSL_COMPUTE)
|
||||
#endif
|
||||
|
||||
#undef CHECK_EVALUATOR_TYPE
|
||||
#undef CHECK_EVALUATOR_TYPE_STUB
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GLMesh structure "methods".
|
||||
|
||||
opensubdiv_capi::GLMeshFVarData *createFVarData(OpenSubdiv::Far::TopologyRefiner *topology_refiner,
|
||||
GLMeshInterface *mesh,
|
||||
const float *fvar_src_buffer)
|
||||
{
|
||||
using opensubdiv_capi::GLMeshFVarData;
|
||||
GLMeshFVarData *fvar_data = new GLMeshFVarData();
|
||||
fvar_data->create(topology_refiner, mesh->GetFarPatchTable(), 2, fvar_src_buffer);
|
||||
return fvar_data;
|
||||
}
|
||||
|
||||
unsigned int getPatchIndexBuffer(OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
return gl_mesh->internal->mesh_interface->GetPatchTable()->GetPatchIndexBuffer();
|
||||
}
|
||||
|
||||
void bindVertexBuffer(OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
gl_mesh->internal->mesh_interface->BindVertexBuffer();
|
||||
}
|
||||
|
||||
void setCoarsePositions(OpenSubdiv_GLMesh *gl_mesh,
|
||||
const float *positions,
|
||||
const int start_vertex,
|
||||
const int num_vertices)
|
||||
{
|
||||
gl_mesh->internal->mesh_interface->UpdateVertexBuffer(positions, start_vertex, num_vertices);
|
||||
}
|
||||
|
||||
void refine(OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
gl_mesh->internal->mesh_interface->Refine();
|
||||
}
|
||||
|
||||
void synchronize(struct OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
gl_mesh->internal->mesh_interface->Synchronize();
|
||||
}
|
||||
|
||||
void assignFunctionPointers(OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
gl_mesh->getPatchIndexBuffer = getPatchIndexBuffer;
|
||||
gl_mesh->bindVertexBuffer = bindVertexBuffer;
|
||||
gl_mesh->setCoarsePositions = setCoarsePositions;
|
||||
gl_mesh->refine = refine;
|
||||
gl_mesh->synchronize = synchronize;
|
||||
|
||||
gl_mesh->prepareDraw = opensubdiv_capi::GLMeshDisplayPrepare;
|
||||
gl_mesh->drawPatches = opensubdiv_capi::GLMeshDisplayDrawPatches;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
struct OpenSubdiv_GLMesh *openSubdiv_createOsdGLMeshFromTopologyRefiner(
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner, eOpenSubdivEvaluator evaluator_type)
|
||||
{
|
||||
using OpenSubdiv::Far::TopologyRefiner;
|
||||
TopologyRefiner *osd_topology_refiner = topology_refiner->internal->osd_topology_refiner;
|
||||
// TODO(sergey): Query this from refiner.
|
||||
const bool is_adaptive = false;
|
||||
MeshBitset bits;
|
||||
bits.set(OpenSubdiv::Osd::MeshAdaptive, is_adaptive);
|
||||
bits.set(OpenSubdiv::Osd::MeshUseSingleCreasePatch, 0);
|
||||
bits.set(OpenSubdiv::Osd::MeshInterleaveVarying, 1);
|
||||
bits.set(OpenSubdiv::Osd::MeshFVarData, 1);
|
||||
bits.set(OpenSubdiv::Osd::MeshEndCapBSplineBasis, 1);
|
||||
const int num_vertex_elements = 3;
|
||||
const int num_varying_elements = 3;
|
||||
GLMeshInterface *mesh = createGLMeshInterface(osd_topology_refiner,
|
||||
bits,
|
||||
num_vertex_elements,
|
||||
num_varying_elements,
|
||||
osd_topology_refiner->GetMaxLevel(),
|
||||
evaluator_type);
|
||||
if (mesh == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
OpenSubdiv_GLMesh *gl_mesh = OBJECT_GUARDED_NEW(OpenSubdiv_GLMesh);
|
||||
assignFunctionPointers(gl_mesh);
|
||||
gl_mesh->internal = new OpenSubdiv_GLMeshInternal();
|
||||
gl_mesh->internal->evaluator_type = evaluator_type;
|
||||
gl_mesh->internal->mesh_interface = mesh;
|
||||
// Face-varying support.
|
||||
// TODO(sergey): This part needs to be re-done.
|
||||
if (osd_topology_refiner->GetNumFVarChannels() > 0) {
|
||||
// TODO(sergey): This is a temporary stub to get things compiled. Need
|
||||
// to store base level UVs somewhere else.
|
||||
vector<float> uvs;
|
||||
vector<float> fvar_data_buffer;
|
||||
opensubdiv_capi::interpolateFVarData(*osd_topology_refiner, uvs, &fvar_data_buffer);
|
||||
gl_mesh->internal->fvar_data = createFVarData(
|
||||
osd_topology_refiner, mesh, &fvar_data_buffer[0]);
|
||||
}
|
||||
else {
|
||||
gl_mesh->internal->fvar_data = NULL;
|
||||
}
|
||||
return gl_mesh;
|
||||
}
|
||||
|
||||
void openSubdiv_deleteOsdGLMesh(OpenSubdiv_GLMesh *gl_mesh)
|
||||
{
|
||||
delete gl_mesh->internal;
|
||||
OBJECT_GUARDED_DELETE(gl_mesh, OpenSubdiv_GLMesh);
|
||||
}
|
@@ -1,577 +0,0 @@
|
||||
// Copyright 2013 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// Author: Sergey Sharybin
|
||||
|
||||
#include "internal/opensubdiv_gl_mesh_draw.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <iso646.h>
|
||||
#endif
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
|
||||
#include <opensubdiv/osd/glMesh.h>
|
||||
|
||||
#ifdef OPENSUBDIV_HAS_CUDA
|
||||
# include <opensubdiv/osd/cudaGLVertexBuffer.h>
|
||||
#endif // OPENSUBDIV_HAS_CUDA
|
||||
|
||||
#include <opensubdiv/osd/cpuEvaluator.h>
|
||||
#include <opensubdiv/osd/cpuGLVertexBuffer.h>
|
||||
|
||||
#include "internal/opensubdiv_gl_mesh_fvar.h"
|
||||
#include "internal/opensubdiv_gl_mesh_internal.h"
|
||||
#include "internal/opensubdiv_util.h"
|
||||
#include "opensubdiv_capi.h"
|
||||
#include "opensubdiv_gl_mesh_capi.h"
|
||||
|
||||
using OpenSubdiv::Osd::GLMeshInterface;
|
||||
|
||||
extern "C" char datatoc_gpu_shader_opensubdiv_vertex_glsl[];
|
||||
extern "C" char datatoc_gpu_shader_opensubdiv_geometry_glsl[];
|
||||
extern "C" char datatoc_gpu_shader_opensubdiv_fragment_glsl[];
|
||||
|
||||
// TODO(sergey): Those are a bit of bad level calls :S
|
||||
extern "C" {
|
||||
void copy_m3_m3(float m1[3][3], float m2[3][3]);
|
||||
void copy_m3_m4(float m1[3][3], float m2[4][4]);
|
||||
void adjoint_m3_m3(float m1[3][3], float m[3][3]);
|
||||
float determinant_m3_array(float m[3][3]);
|
||||
bool invert_m3_m3(float m1[3][3], float m2[3][3]);
|
||||
bool invert_m3(float m[3][3]);
|
||||
void transpose_m3(float mat[3][3]);
|
||||
}
|
||||
|
||||
#define MAX_LIGHTS 8
|
||||
#define SUPPORT_COLOR_MATERIAL
|
||||
|
||||
typedef struct Light {
|
||||
float position[4];
|
||||
float ambient[4];
|
||||
float diffuse[4];
|
||||
float specular[4];
|
||||
float spot_direction[4];
|
||||
#ifdef SUPPORT_COLOR_MATERIAL
|
||||
float constant_attenuation;
|
||||
float linear_attenuation;
|
||||
float quadratic_attenuation;
|
||||
float spot_cutoff;
|
||||
float spot_exponent;
|
||||
float spot_cos_cutoff;
|
||||
float pad, pad2;
|
||||
#endif
|
||||
} Light;
|
||||
|
||||
typedef struct Lighting {
|
||||
Light lights[MAX_LIGHTS];
|
||||
int num_enabled;
|
||||
} Lighting;
|
||||
|
||||
typedef struct Transform {
|
||||
float projection_matrix[16];
|
||||
float model_view_matrix[16];
|
||||
float normal_matrix[9];
|
||||
} Transform;
|
||||
|
||||
static bool g_use_osd_glsl = false;
|
||||
static int g_active_uv_index = 0;
|
||||
|
||||
static GLuint g_flat_fill_solid_program = 0;
|
||||
static GLuint g_flat_fill_texture2d_program = 0;
|
||||
static GLuint g_smooth_fill_solid_program = 0;
|
||||
static GLuint g_smooth_fill_texture2d_program = 0;
|
||||
|
||||
static GLuint g_flat_fill_solid_shadeless_program = 0;
|
||||
static GLuint g_flat_fill_texture2d_shadeless_program = 0;
|
||||
static GLuint g_smooth_fill_solid_shadeless_program = 0;
|
||||
static GLuint g_smooth_fill_texture2d_shadeless_program = 0;
|
||||
|
||||
static GLuint g_wireframe_program = 0;
|
||||
|
||||
static GLuint g_lighting_ub = 0;
|
||||
static Lighting g_lighting_data;
|
||||
static Transform g_transform;
|
||||
|
||||
namespace {
|
||||
|
||||
GLuint compileShader(GLenum shaderType,
|
||||
const char *version,
|
||||
const char *define,
|
||||
const char *source)
|
||||
{
|
||||
const char *sources[] = {
|
||||
version,
|
||||
define,
|
||||
#ifdef SUPPORT_COLOR_MATERIAL
|
||||
"#define SUPPORT_COLOR_MATERIAL\n",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
source,
|
||||
};
|
||||
|
||||
GLuint shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 4, sources, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint status;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if (status == GL_FALSE) {
|
||||
GLchar emsg[1024];
|
||||
glGetShaderInfoLog(shader, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error compiling GLSL: %s\n", emsg);
|
||||
fprintf(stderr, "Version: %s\n", version);
|
||||
fprintf(stderr, "Defines: %s\n", define);
|
||||
fprintf(stderr, "Source: %s\n", source);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint linkProgram(const char *version, const char *define)
|
||||
{
|
||||
GLuint vertexShader = compileShader(
|
||||
GL_VERTEX_SHADER, version, define, datatoc_gpu_shader_opensubdiv_vertex_glsl);
|
||||
if (vertexShader == 0) {
|
||||
return 0;
|
||||
}
|
||||
GLuint geometryShader = compileShader(
|
||||
GL_GEOMETRY_SHADER, version, define, datatoc_gpu_shader_opensubdiv_geometry_glsl);
|
||||
if (geometryShader == 0) {
|
||||
return 0;
|
||||
}
|
||||
GLuint fragmentShader = compileShader(
|
||||
GL_FRAGMENT_SHADER, version, define, datatoc_gpu_shader_opensubdiv_fragment_glsl);
|
||||
if (fragmentShader == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
|
||||
glAttachShader(program, vertexShader);
|
||||
glAttachShader(program, geometryShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
|
||||
glBindAttribLocation(program, 0, "position");
|
||||
glBindAttribLocation(program, 1, "normal");
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(geometryShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE) {
|
||||
GLchar emsg[1024];
|
||||
glGetProgramInfoLog(program, sizeof(emsg), 0, emsg);
|
||||
fprintf(stderr, "Error linking GLSL program : %s\n", emsg);
|
||||
fprintf(stderr, "Defines: %s\n", define);
|
||||
glDeleteProgram(program);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glUniformBlockBinding(program, glGetUniformBlockIndex(program, "Lighting"), 0);
|
||||
|
||||
if (GLEW_VERSION_4_1) {
|
||||
glProgramUniform1i(program, glGetUniformLocation(program, "texture_buffer"), 0);
|
||||
glProgramUniform1i(program, glGetUniformLocation(program, "FVarDataOffsetBuffer"), 30);
|
||||
glProgramUniform1i(program, glGetUniformLocation(program, "FVarDataBuffer"), 31);
|
||||
}
|
||||
else {
|
||||
glUseProgram(program);
|
||||
glUniform1i(glGetUniformLocation(program, "texture_buffer"), 0);
|
||||
glUniform1i(glGetUniformLocation(program, "FVarDataOffsetBuffer"), 30);
|
||||
glUniform1i(glGetUniformLocation(program, "FVarDataBuffer"), 31);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
void bindProgram(OpenSubdiv_GLMesh *gl_mesh, int program)
|
||||
{
|
||||
glUseProgram(program);
|
||||
// Matrices
|
||||
glUniformMatrix4fv(
|
||||
glGetUniformLocation(program, "modelViewMatrix"), 1, false, g_transform.model_view_matrix);
|
||||
glUniformMatrix4fv(
|
||||
glGetUniformLocation(program, "projectionMatrix"), 1, false, g_transform.projection_matrix);
|
||||
glUniformMatrix3fv(
|
||||
glGetUniformLocation(program, "normalMatrix"), 1, false, g_transform.normal_matrix);
|
||||
// Lighting.
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
|
||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(g_lighting_data), &g_lighting_data);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, g_lighting_ub);
|
||||
// Color.
|
||||
{
|
||||
// TODO(sergey): Stop using glGetMaterial.
|
||||
float color[4];
|
||||
glGetMaterialfv(GL_FRONT, GL_DIFFUSE, color);
|
||||
glUniform4fv(glGetUniformLocation(program, "diffuse"), 1, color);
|
||||
glGetMaterialfv(GL_FRONT, GL_SPECULAR, color);
|
||||
glUniform4fv(glGetUniformLocation(program, "specular"), 1, color);
|
||||
glGetMaterialfv(GL_FRONT, GL_SHININESS, color);
|
||||
glUniform1f(glGetUniformLocation(program, "shininess"), color[0]);
|
||||
}
|
||||
// Face-vertex data.
|
||||
opensubdiv_capi::GLMeshFVarData *fvar_data = gl_mesh->internal->fvar_data;
|
||||
if (fvar_data != NULL) {
|
||||
if (fvar_data->texture_buffer) {
|
||||
glActiveTexture(GL_TEXTURE31);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, fvar_data->texture_buffer);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
if (fvar_data->offset_buffer) {
|
||||
glActiveTexture(GL_TEXTURE30);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, fvar_data->offset_buffer);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), fvar_data->fvar_width);
|
||||
if (fvar_data->channel_offsets.size() > 0 && g_active_uv_index >= 0) {
|
||||
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"),
|
||||
fvar_data->channel_offsets[g_active_uv_index]);
|
||||
}
|
||||
else {
|
||||
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
|
||||
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool openSubdiv_initGLMeshDrawingResources(void)
|
||||
{
|
||||
static bool need_init = true;
|
||||
static bool init_success = false;
|
||||
if (!need_init) {
|
||||
return init_success;
|
||||
}
|
||||
// TODO(sergey): Update OSD drawing to OpenGL 3.3 core,
|
||||
// then remove following line.
|
||||
return false;
|
||||
const char *version = "";
|
||||
if (GLEW_VERSION_3_2) {
|
||||
version = "#version 150 compatibility\n";
|
||||
}
|
||||
else if (GLEW_VERSION_3_1) {
|
||||
version =
|
||||
"#version 140\n"
|
||||
"#extension GL_ARB_compatibility: enable\n";
|
||||
}
|
||||
else {
|
||||
version = "#version 130\n";
|
||||
// Minimum supported for OpenSubdiv.
|
||||
}
|
||||
g_flat_fill_solid_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define USE_LIGHTING\n"
|
||||
"#define FLAT_SHADING\n");
|
||||
g_flat_fill_texture2d_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define USE_LIGHTING\n"
|
||||
"#define USE_TEXTURE_2D\n"
|
||||
"#define FLAT_SHADING\n");
|
||||
g_smooth_fill_solid_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define USE_LIGHTING\n"
|
||||
"#define SMOOTH_SHADING\n");
|
||||
g_smooth_fill_texture2d_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define USE_LIGHTING\n"
|
||||
"#define USE_TEXTURE_2D\n"
|
||||
"#define SMOOTH_SHADING\n");
|
||||
|
||||
g_flat_fill_solid_shadeless_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define FLAT_SHADING\n");
|
||||
g_flat_fill_texture2d_shadeless_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define USE_TEXTURE_2D\n"
|
||||
"#define FLAT_SHADING\n");
|
||||
g_smooth_fill_solid_shadeless_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define SMOOTH_SHADING\n");
|
||||
g_smooth_fill_texture2d_shadeless_program = linkProgram(version,
|
||||
"#define USE_COLOR_MATERIAL\n"
|
||||
"#define USE_TEXTURE_2D\n"
|
||||
"#define SMOOTH_SHADING\n");
|
||||
g_wireframe_program = linkProgram(version, "#define WIREFRAME\n");
|
||||
|
||||
glGenBuffers(1, &g_lighting_ub);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, g_lighting_ub);
|
||||
glBufferData(GL_UNIFORM_BUFFER, sizeof(g_lighting_data), NULL, GL_STATIC_DRAW);
|
||||
need_init = false;
|
||||
init_success = g_flat_fill_solid_program != 0 && g_flat_fill_texture2d_program != 0 &&
|
||||
g_smooth_fill_solid_program != 0 && g_smooth_fill_texture2d_program != 0 &&
|
||||
g_wireframe_program;
|
||||
return init_success;
|
||||
}
|
||||
|
||||
void openSubdiv_deinitGLMeshDrawingResources(void)
|
||||
{
|
||||
if (g_lighting_ub != 0) {
|
||||
glDeleteBuffers(1, &g_lighting_ub);
|
||||
}
|
||||
#define SAFE_DELETE_PROGRAM(program) \
|
||||
do { \
|
||||
if (program) { \
|
||||
glDeleteProgram(program); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
SAFE_DELETE_PROGRAM(g_flat_fill_solid_program);
|
||||
SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_program);
|
||||
SAFE_DELETE_PROGRAM(g_smooth_fill_solid_program);
|
||||
SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_program);
|
||||
SAFE_DELETE_PROGRAM(g_flat_fill_solid_shadeless_program);
|
||||
SAFE_DELETE_PROGRAM(g_flat_fill_texture2d_shadeless_program);
|
||||
SAFE_DELETE_PROGRAM(g_smooth_fill_solid_shadeless_program);
|
||||
SAFE_DELETE_PROGRAM(g_smooth_fill_texture2d_shadeless_program);
|
||||
SAFE_DELETE_PROGRAM(g_wireframe_program);
|
||||
|
||||
#undef SAFE_DELETE_PROGRAM
|
||||
}
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
|
||||
namespace {
|
||||
|
||||
GLuint prepare_patchDraw(OpenSubdiv_GLMesh *gl_mesh, bool fill_quads)
|
||||
{
|
||||
GLint program = 0;
|
||||
if (!g_use_osd_glsl) {
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &program);
|
||||
if (program) {
|
||||
GLint model;
|
||||
glGetIntegerv(GL_SHADE_MODEL, &model);
|
||||
GLint location = glGetUniformLocation(program, "osd_flat_shading");
|
||||
if (location != -1) {
|
||||
glUniform1i(location, model == GL_FLAT);
|
||||
}
|
||||
// Face-vertex data.
|
||||
opensubdiv_capi::GLMeshFVarData *fvar_data = gl_mesh->internal->fvar_data;
|
||||
if (fvar_data != NULL) {
|
||||
if (fvar_data->texture_buffer) {
|
||||
glActiveTexture(GL_TEXTURE31);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, fvar_data->texture_buffer);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
if (fvar_data->offset_buffer) {
|
||||
glActiveTexture(GL_TEXTURE30);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, fvar_data->offset_buffer);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
GLint location = glGetUniformLocation(program, "osd_fvar_count");
|
||||
if (location != -1) {
|
||||
glUniform1i(location, fvar_data->fvar_width);
|
||||
}
|
||||
location = glGetUniformLocation(program, "osd_active_uv_offset");
|
||||
if (location != -1) {
|
||||
if (fvar_data->channel_offsets.size() > 0 && g_active_uv_index >= 0) {
|
||||
glUniform1i(location, fvar_data->channel_offsets[g_active_uv_index]);
|
||||
}
|
||||
else {
|
||||
glUniform1i(location, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
glUniform1i(glGetUniformLocation(program, "osd_fvar_count"), 0);
|
||||
glUniform1i(glGetUniformLocation(program, "osd_active_uv_offset"), 0);
|
||||
}
|
||||
}
|
||||
return program;
|
||||
}
|
||||
if (fill_quads) {
|
||||
int model;
|
||||
GLboolean use_texture_2d;
|
||||
glGetIntegerv(GL_SHADE_MODEL, &model);
|
||||
glGetBooleanv(GL_TEXTURE_2D, &use_texture_2d);
|
||||
if (model == GL_FLAT) {
|
||||
if (use_texture_2d) {
|
||||
program = g_flat_fill_texture2d_program;
|
||||
}
|
||||
else {
|
||||
program = g_flat_fill_solid_program;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (use_texture_2d) {
|
||||
program = g_smooth_fill_texture2d_program;
|
||||
}
|
||||
else {
|
||||
program = g_smooth_fill_solid_program;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
program = g_wireframe_program;
|
||||
}
|
||||
bindProgram(gl_mesh, program);
|
||||
return program;
|
||||
}
|
||||
|
||||
void perform_drawElements(GLuint program, int patch_index, int num_elements, int start_element)
|
||||
{
|
||||
if (program) {
|
||||
glUniform1i(glGetUniformLocation(program, "PrimitiveIdBase"), patch_index);
|
||||
}
|
||||
glDrawElements(GL_LINES_ADJACENCY,
|
||||
num_elements,
|
||||
GL_UNSIGNED_INT,
|
||||
reinterpret_cast<void *>(start_element * sizeof(unsigned int)));
|
||||
}
|
||||
|
||||
void finishPatchDraw(bool fill_quads)
|
||||
{
|
||||
// TODO(sergey): Some of the stuff could be done once after the whole
|
||||
// mesh is displayed.
|
||||
/// Restore state.
|
||||
if (!fill_quads) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
if (g_use_osd_glsl) {
|
||||
// TODO(sergey): Store previously used program and roll back to it?
|
||||
glUseProgram(0);
|
||||
}
|
||||
}
|
||||
|
||||
void drawPartitionPatchesRange(GLMeshInterface *mesh,
|
||||
GLuint program,
|
||||
int start_patch,
|
||||
int num_patches)
|
||||
{
|
||||
int traversed_patches = 0, num_remained_patches = num_patches;
|
||||
const OpenSubdiv::Osd::PatchArrayVector &patches = mesh->GetPatchTable()->GetPatchArrays();
|
||||
for (int i = 0; i < patches.size(); ++i) {
|
||||
const OpenSubdiv::Osd::PatchArray &patch = patches[i];
|
||||
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
|
||||
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
|
||||
if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
|
||||
const int num_block_patches = patch.GetNumPatches();
|
||||
if (start_patch >= traversed_patches &&
|
||||
start_patch < traversed_patches + num_block_patches) {
|
||||
const int num_control_verts = desc.GetNumControlVertices();
|
||||
const int start_draw_patch = start_patch - traversed_patches;
|
||||
const int num_draw_patches = min(num_remained_patches,
|
||||
num_block_patches - start_draw_patch);
|
||||
perform_drawElements(program,
|
||||
i + start_draw_patch,
|
||||
num_draw_patches * num_control_verts,
|
||||
patch.GetIndexBase() + start_draw_patch * num_control_verts);
|
||||
num_remained_patches -= num_draw_patches;
|
||||
}
|
||||
if (num_remained_patches == 0) {
|
||||
break;
|
||||
}
|
||||
traversed_patches += num_block_patches;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void drawAllPatches(GLMeshInterface *mesh, GLuint program)
|
||||
{
|
||||
const OpenSubdiv::Osd::PatchArrayVector &patches = mesh->GetPatchTable()->GetPatchArrays();
|
||||
for (int i = 0; i < patches.size(); ++i) {
|
||||
const OpenSubdiv::Osd::PatchArray &patch = patches[i];
|
||||
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
|
||||
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
|
||||
|
||||
if (patchType == OpenSubdiv::Far::PatchDescriptor::QUADS) {
|
||||
perform_drawElements(
|
||||
program, i, patch.GetNumPatches() * desc.GetNumControlVertices(), patch.GetIndexBase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void GLMeshDisplayPrepare(struct OpenSubdiv_GLMesh * /*gl_mesh*/,
|
||||
const bool use_osd_glsl,
|
||||
const int active_uv_index)
|
||||
{
|
||||
g_active_uv_index = active_uv_index;
|
||||
g_use_osd_glsl = (use_osd_glsl != 0);
|
||||
// Update transformation matrices.
|
||||
glGetFloatv(GL_PROJECTION_MATRIX, g_transform.projection_matrix);
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, g_transform.model_view_matrix);
|
||||
copy_m3_m4((float(*)[3])g_transform.normal_matrix, (float(*)[4])g_transform.model_view_matrix);
|
||||
invert_m3((float(*)[3])g_transform.normal_matrix);
|
||||
transpose_m3((float(*)[3])g_transform.normal_matrix);
|
||||
// Update OpenGL lights positions, colors etc.
|
||||
g_lighting_data.num_enabled = 0;
|
||||
for (int i = 0; i < MAX_LIGHTS; ++i) {
|
||||
GLboolean enabled;
|
||||
glGetBooleanv(GL_LIGHT0 + i, &enabled);
|
||||
if (enabled) {
|
||||
g_lighting_data.num_enabled++;
|
||||
}
|
||||
// TODO(sergey): Stop using glGetLight.
|
||||
glGetLightfv(GL_LIGHT0 + i, GL_POSITION, g_lighting_data.lights[i].position);
|
||||
glGetLightfv(GL_LIGHT0 + i, GL_AMBIENT, g_lighting_data.lights[i].ambient);
|
||||
glGetLightfv(GL_LIGHT0 + i, GL_DIFFUSE, g_lighting_data.lights[i].diffuse);
|
||||
glGetLightfv(GL_LIGHT0 + i, GL_SPECULAR, g_lighting_data.lights[i].specular);
|
||||
glGetLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, g_lighting_data.lights[i].spot_direction);
|
||||
#ifdef SUPPORT_COLOR_MATERIAL
|
||||
glGetLightfv(
|
||||
GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &g_lighting_data.lights[i].constant_attenuation);
|
||||
glGetLightfv(
|
||||
GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &g_lighting_data.lights[i].linear_attenuation);
|
||||
glGetLightfv(
|
||||
GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &g_lighting_data.lights[i].quadratic_attenuation);
|
||||
glGetLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &g_lighting_data.lights[i].spot_cutoff);
|
||||
glGetLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &g_lighting_data.lights[i].spot_exponent);
|
||||
g_lighting_data.lights[i].spot_cos_cutoff = cos(g_lighting_data.lights[i].spot_cutoff);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GLMeshDisplayDrawPatches(OpenSubdiv_GLMesh *gl_mesh,
|
||||
const bool fill_quads,
|
||||
const int start_patch,
|
||||
const int num_patches)
|
||||
{
|
||||
GLMeshInterface *mesh = gl_mesh->internal->mesh_interface;
|
||||
// Make sure all global invariants are initialized.
|
||||
if (!openSubdiv_initGLMeshDrawingResources()) {
|
||||
return;
|
||||
}
|
||||
/// Setup GLSL/OpenGL to draw patches in current context.
|
||||
GLuint program = prepare_patchDraw(gl_mesh, fill_quads != 0);
|
||||
if (start_patch != -1) {
|
||||
drawPartitionPatchesRange(mesh, program, start_patch, num_patches);
|
||||
}
|
||||
else {
|
||||
drawAllPatches(mesh, program);
|
||||
}
|
||||
// Finish patch drawing by restoring all changes to the OpenGL context.
|
||||
finishPatchDraw(fill_quads != 0);
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
@@ -1,39 +0,0 @@
|
||||
// Copyright 2013 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// Author: Sergey Sharybin
|
||||
|
||||
#ifndef OPENSUBDIV_GL_MESH_DRAW_H_
|
||||
#define OPENSUBDIV_GL_MESH_DRAW_H_
|
||||
|
||||
#include <stdint.h> // for bool
|
||||
|
||||
struct OpenSubdiv_GLMesh;
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
|
||||
void GLMeshDisplayPrepare(struct OpenSubdiv_GLMesh *gl_mesh,
|
||||
const bool use_osd_glsl,
|
||||
const int active_uv_index);
|
||||
|
||||
void GLMeshDisplayDrawPatches(OpenSubdiv_GLMesh *gl_mesh,
|
||||
const bool fill_quads,
|
||||
const int start_patch,
|
||||
const int num_patches);
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
|
||||
#endif // OPENSUBDIV_GL_MESH_DRAW_H_
|
@@ -1,171 +0,0 @@
|
||||
// Copyright 2013 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// Author: Sergey Sharybin
|
||||
|
||||
#include "internal/opensubdiv_gl_mesh_fvar.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <opensubdiv/far/primvarRefiner.h>
|
||||
|
||||
#include "internal/opensubdiv_util.h"
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GLMeshFVarData
|
||||
|
||||
GLMeshFVarData::GLMeshFVarData() : texture_buffer(0), offset_buffer(0)
|
||||
{
|
||||
}
|
||||
|
||||
GLMeshFVarData::~GLMeshFVarData()
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
void GLMeshFVarData::release()
|
||||
{
|
||||
if (texture_buffer) {
|
||||
glDeleteTextures(1, &texture_buffer);
|
||||
}
|
||||
if (offset_buffer) {
|
||||
glDeleteTextures(1, &offset_buffer);
|
||||
}
|
||||
texture_buffer = 0;
|
||||
offset_buffer = 0;
|
||||
fvar_width = 0;
|
||||
channel_offsets.clear();
|
||||
}
|
||||
|
||||
void GLMeshFVarData::create(const OpenSubdiv::Far::TopologyRefiner *topology_refiner,
|
||||
const OpenSubdiv::Far::PatchTable *patch_table,
|
||||
int fvar_width,
|
||||
const float *fvar_src_data)
|
||||
{
|
||||
release();
|
||||
this->fvar_width = fvar_width;
|
||||
/// Expand fvar data to per-patch array.
|
||||
const int max_level = topology_refiner->GetMaxLevel();
|
||||
const int num_channels = patch_table->GetNumFVarChannels();
|
||||
vector<float> data;
|
||||
int fvar_data_offset = 0;
|
||||
channel_offsets.resize(num_channels);
|
||||
for (int channel = 0; channel < num_channels; ++channel) {
|
||||
OpenSubdiv::Far::ConstIndexArray indices = patch_table->GetFVarValues(channel);
|
||||
channel_offsets[channel] = data.size();
|
||||
data.reserve(data.size() + indices.size() * fvar_width);
|
||||
for (int fvert = 0; fvert < indices.size(); ++fvert) {
|
||||
int index = indices[fvert] * fvar_width;
|
||||
for (int i = 0; i < fvar_width; ++i) {
|
||||
data.push_back(fvar_src_data[fvar_data_offset + index++]);
|
||||
}
|
||||
}
|
||||
if (topology_refiner->IsUniform()) {
|
||||
const int num_values_max = topology_refiner->GetLevel(max_level).GetNumFVarValues(channel);
|
||||
fvar_data_offset += num_values_max * fvar_width;
|
||||
}
|
||||
else {
|
||||
const int num_values_total = topology_refiner->GetNumFVarValuesTotal(channel);
|
||||
fvar_data_offset += num_values_total * fvar_width;
|
||||
}
|
||||
}
|
||||
GLuint buffer;
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(float), &data[0], GL_STATIC_DRAW);
|
||||
glGenTextures(1, &texture_buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, texture_buffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
|
||||
glDeleteBuffers(1, &buffer);
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(
|
||||
GL_ARRAY_BUFFER, channel_offsets.size() * sizeof(int), &channel_offsets[0], GL_STATIC_DRAW);
|
||||
glGenTextures(1, &offset_buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, offset_buffer);
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper functions.
|
||||
|
||||
struct FVarVertex {
|
||||
float u, v;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
u = v = 0.0f;
|
||||
}
|
||||
|
||||
void AddWithWeight(FVarVertex const &src, float weight)
|
||||
{
|
||||
u += weight * src.u;
|
||||
v += weight * src.v;
|
||||
}
|
||||
};
|
||||
|
||||
void interpolateFVarData(const OpenSubdiv::Far::TopologyRefiner &refiner,
|
||||
const vector<float> &uvs,
|
||||
vector<float> *fvar_data)
|
||||
{
|
||||
const int fvar_width = 2;
|
||||
const int max_level = refiner.GetMaxLevel();
|
||||
size_t fvar_data_offset = 0, values_offset = 0;
|
||||
for (int channel = 0; channel < refiner.GetNumFVarChannels(); ++channel) {
|
||||
const int num_values = refiner.GetLevel(0).GetNumFVarValues(channel) * 2;
|
||||
const int num_values_max = refiner.GetLevel(max_level).GetNumFVarValues(channel);
|
||||
const int num_values_total = refiner.GetNumFVarValuesTotal(channel);
|
||||
if (num_values_total <= 0) {
|
||||
continue;
|
||||
}
|
||||
OpenSubdiv::Far::PrimvarRefiner primvar_refiner(refiner);
|
||||
if (refiner.IsUniform()) {
|
||||
// For uniform we only keep the highest level of refinement.
|
||||
fvar_data->resize(fvar_data->size() + num_values_max * fvar_width);
|
||||
vector<FVarVertex> buffer(num_values_total - num_values_max);
|
||||
FVarVertex *src = &buffer[0];
|
||||
memcpy(src, &uvs[values_offset], num_values * sizeof(float));
|
||||
// Defer the last level to treat separately with its alternate
|
||||
// destination.
|
||||
for (int level = 1; level < max_level; ++level) {
|
||||
FVarVertex *dst = src + refiner.GetLevel(level - 1).GetNumFVarValues(channel);
|
||||
primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
|
||||
src = dst;
|
||||
}
|
||||
FVarVertex *dst = reinterpret_cast<FVarVertex *>(&(*fvar_data)[fvar_data_offset]);
|
||||
primvar_refiner.InterpolateFaceVarying(max_level, src, dst, channel);
|
||||
fvar_data_offset += num_values_max * fvar_width;
|
||||
}
|
||||
else {
|
||||
// For adaptive we keep all levels.
|
||||
fvar_data->resize(fvar_data->size() + num_values_total * fvar_width);
|
||||
FVarVertex *src = reinterpret_cast<FVarVertex *>(&(*fvar_data)[fvar_data_offset]);
|
||||
memcpy(src, &uvs[values_offset], num_values * sizeof(float));
|
||||
for (int level = 1; level <= max_level; ++level) {
|
||||
FVarVertex *dst = src + refiner.GetLevel(level - 1).GetNumFVarValues(channel);
|
||||
primvar_refiner.InterpolateFaceVarying(level, src, dst, channel);
|
||||
src = dst;
|
||||
}
|
||||
fvar_data_offset += num_values_total * fvar_width;
|
||||
}
|
||||
values_offset += num_values;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace opensubdiv_capi
|
@@ -1,57 +0,0 @@
|
||||
// Copyright 2013 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software Foundation,
|
||||
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// Author: Sergey Sharybin
|
||||
|
||||
#ifndef OPENSUBDIV_GL_MESH_FVAR_H_
|
||||
#define OPENSUBDIV_GL_MESH_FVAR_H_
|
||||
|
||||
// NOTE: This is a [sane(er)] port of previous ground work for getting UVs to
|
||||
// work. Still needs a lot of work to make it easy, correct and have proper
|
||||
// data ownership.
|
||||
|
||||
#include <opensubdiv/far/patchTable.h>
|
||||
#include <opensubdiv/far/topologyRefiner.h>
|
||||
|
||||
#include "internal/opensubdiv_util.h"
|
||||
|
||||
namespace opensubdiv_capi {
|
||||
|
||||
// The buffer which holds GPU resources for face-varying elements.
|
||||
class GLMeshFVarData {
|
||||
public:
|
||||
GLMeshFVarData();
|
||||
~GLMeshFVarData();
|
||||
|
||||
void release();
|
||||
void create(const OpenSubdiv::Far::TopologyRefiner *refiner,
|
||||
const OpenSubdiv::Far::PatchTable *patch_table,
|
||||
int fvar_width,
|
||||
const float *fvar_src_data);
|
||||
|
||||
unsigned int texture_buffer;
|
||||
unsigned int offset_buffer;
|
||||
vector<int> channel_offsets;
|
||||
int fvar_width;
|
||||
};
|
||||
|
||||
void interpolateFVarData(const OpenSubdiv::Far::TopologyRefiner &refiner,
|
||||
const vector<float> &uvs,
|
||||
vector<float> *fvar_data);
|
||||
|
||||
} // namespace opensubdiv_capi
|
||||
|
||||
#endif // OPENSUBDIV_GL_MESH_FVAR_H_
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user