Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-05-27 12:06:29 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-05-27 12:06:29 +0300
commit9a74b603670cc3fab14d9fcd7be7b3c17731a8ee (patch)
tree0611021c1450e586308d58223353793dcc137afe
parent474971f3d84e5eacde7e92fc86ef4e10a5e0786c (diff)
parentbc3727a94374d9c56745c943a1e6574627a88510 (diff)
Merge branch 'master' into blender2.8
-rw-r--r--build_files/cmake/platform/platform_win32.cmake2
-rw-r--r--build_files/windows/autodetect_msvc.cmd17
-rw-r--r--build_files/windows/build_msbuild.cmd26
-rw-r--r--build_files/windows/build_ninja.cmd16
-rw-r--r--build_files/windows/check_libraries.cmd54
-rw-r--r--build_files/windows/check_spaces_in_path.cmd6
-rw-r--r--build_files/windows/check_submodules.cmd20
-rw-r--r--build_files/windows/configure_msbuild.cmd59
-rw-r--r--build_files/windows/configure_ninja.cmd35
-rw-r--r--build_files/windows/detect_architecture.cmd16
-rw-r--r--build_files/windows/detect_msvc2013.cmd3
-rw-r--r--build_files/windows/detect_msvc2015.cmd3
-rw-r--r--build_files/windows/detect_msvc2017.cmd70
-rw-r--r--build_files/windows/detect_msvc_classic.cmd69
-rw-r--r--build_files/windows/find_dependencies.cmd13
-rw-r--r--build_files/windows/parse_arguments.cmd78
-rw-r--r--build_files/windows/reset_variables.cmd23
-rw-r--r--build_files/windows/set_build_dir.cmd4
-rw-r--r--build_files/windows/show_hashes.cmd12
-rw-r--r--build_files/windows/show_help.cmd29
-rw-r--r--build_files/windows/update_sources.cmd16
-rw-r--r--intern/cycles/blender/blender_shader.cpp13
-rw-r--r--intern/cycles/blender/blender_util.h15
-rw-r--r--intern/cycles/graph/node_type.h13
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/kernel_light.h4
-rw-r--r--intern/cycles/kernel/kernel_textures.h3
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp8
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/shaders/node_ies_light.osl42
-rw-r--r--intern/cycles/kernel/svm/svm.h4
-rw-r--r--intern/cycles/kernel/svm/svm_ies.h110
-rw-r--r--intern/cycles/kernel/svm/svm_types.h1
-rw-r--r--intern/cycles/render/graph.cpp6
-rw-r--r--intern/cycles/render/light.cpp122
-rw-r--r--intern/cycles/render/light.h17
-rw-r--r--intern/cycles/render/nodes.cpp100
-rw-r--r--intern/cycles/render/nodes.h22
-rw-r--r--intern/cycles/render/osl.cpp9
-rw-r--r--intern/cycles/render/osl.h5
-rw-r--r--intern/cycles/render/scene.cpp3
-rw-r--r--intern/cycles/render/scene.h3
-rw-r--r--intern/cycles/render/svm.cpp7
-rw-r--r--intern/cycles/render/svm.h5
-rw-r--r--intern/cycles/util/CMakeLists.txt2
-rw-r--r--intern/cycles/util/util_ies.cpp392
-rw-r--r--intern/cycles/util/util_ies.h61
-rw-r--r--intern/cycles/util/util_math.h11
-rw-r--r--make.bat371
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py3
-rw-r--r--release/scripts/startup/nodeitems_builtins.py1
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/bpath.c8
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/pointcache.c17
-rw-r--r--source/blender/blenlib/BLI_string.h1
-rw-r--r--source/blender/blenlib/intern/string.c36
-rw-r--r--source/blender/blenlib/intern/threads.c3
-rw-r--r--source/blender/editors/space_info/info_stats.c18
-rw-r--r--source/blender/editors/space_node/drawnode.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c10
-rw-r--r--source/blender/makesdna/DNA_node_types.h9
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c56
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ies_light.c61
-rw-r--r--tests/gtests/blenlib/BLI_string_test.cc66
69 files changed, 1862 insertions, 373 deletions
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index 7e978a71ad4..606e4e59571 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -119,6 +119,8 @@ set(CMAKE_INSTALL_OPENMP_LIBRARIES ${WITH_OPENMP})
set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .)
include(InstallRequiredSystemLibraries)
+remove_cc_flag("/MDd" "/MD")
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /nologo /J /Gd /MP /EHsc")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP")
diff --git a/build_files/windows/autodetect_msvc.cmd b/build_files/windows/autodetect_msvc.cmd
new file mode 100644
index 00000000000..6fce3829e7b
--- /dev/null
+++ b/build_files/windows/autodetect_msvc.cmd
@@ -0,0 +1,17 @@
+echo No explicit msvc version requested, autodetecting version.
+
+call "%~dp0\detect_msvc2013.cmd"
+if %ERRORLEVEL% EQU 0 goto DetectionComplete
+
+call "%~dp0\detect_msvc2015.cmd"
+if %ERRORLEVEL% EQU 0 goto DetectionComplete
+
+call "%~dp0\detect_msvc2017.cmd"
+if %ERRORLEVEL% EQU 0 goto DetectionComplete
+
+echo Compiler Detection failed. Use verbose switch for more information.
+exit /b 1
+
+:DetectionComplete
+echo Compiler Detection successfull, detected VS%BUILD_VS_YEAR%
+exit /b 0 \ No newline at end of file
diff --git a/build_files/windows/build_msbuild.cmd b/build_files/windows/build_msbuild.cmd
new file mode 100644
index 00000000000..6ca5f1b0df8
--- /dev/null
+++ b/build_files/windows/build_msbuild.cmd
@@ -0,0 +1,26 @@
+if "%NOBUILD%"=="1" goto EOF
+echo %TIME% > %BUILD_DIR%\buildtime.txt
+msbuild ^
+ %BUILD_DIR%\Blender.sln ^
+ /target:build ^
+ /property:Configuration=%BUILD_TYPE% ^
+ /maxcpucount:2 ^
+ /verbosity:minimal ^
+ /p:platform=%MSBUILD_PLATFORM% ^
+ /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log
+ if errorlevel 1 (
+ echo Error during build, see %BUILD_DIR%\Build.log for details
+ exit /b 1
+ )
+
+msbuild ^
+ %BUILD_DIR%\INSTALL.vcxproj ^
+ /property:Configuration=%BUILD_TYPE% ^
+ /verbosity:minimal ^
+ /p:platform=%MSBUILD_PLATFORM%
+ if errorlevel 1 (
+ echo Error during install phase
+ exit /b 1
+ )
+echo %TIME% >> %BUILD_DIR%\buildtime.txt
+:EOF \ No newline at end of file
diff --git a/build_files/windows/build_ninja.cmd b/build_files/windows/build_ninja.cmd
new file mode 100644
index 00000000000..f6b266e206d
--- /dev/null
+++ b/build_files/windows/build_ninja.cmd
@@ -0,0 +1,16 @@
+if "%NOBUILD%"=="1" goto EOF
+set HAS_ERROR=
+cd %BUILD_DIR%
+echo %TIME% > buildtime.txt
+ninja install
+if errorlevel 1 (
+ set HAS_ERROR=1
+ )
+echo %TIME% >>buildtime.txt
+cd %BLENDER_DIR%
+
+if "%HAS_ERROR%" == "1" (
+ echo Error during build, see %BUILD_DIR%\Build.log for details
+ exit /b 1
+)
+:EOF \ No newline at end of file
diff --git a/build_files/windows/check_libraries.cmd b/build_files/windows/check_libraries.cmd
new file mode 100644
index 00000000000..c8aad7c9adb
--- /dev/null
+++ b/build_files/windows/check_libraries.cmd
@@ -0,0 +1,54 @@
+if "%BUILD_VS_YEAR%"=="2013" set BUILD_VS_LIBDIRPOST=vc12
+if "%BUILD_VS_YEAR%"=="2015" set BUILD_VS_LIBDIRPOST=vc14
+if "%BUILD_VS_YEAR%"=="2017" set BUILD_VS_LIBDIRPOST=vc14
+
+if "%BUILD_ARCH%"=="x64" (
+ set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
+) else if "%BUILD_ARCH%"=="x86" (
+ set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST%
+)
+set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
+
+if NOT "%verbose%" == "" (
+ echo Library Directory = "%BUILD_VS_LIBDIR%"
+)
+if NOT EXIST %BUILD_VS_LIBDIR% (
+ rem libs not found, but svn is on the system
+ echo
+ if not "%SVN%"=="" (
+ echo.
+ echo The required external libraries in %BUILD_VS_LIBDIR% are missing
+ echo.
+ set /p GetLibs= "Would you like to download them? (y/n)"
+ if /I "!GetLibs!"=="Y" (
+ echo.
+ echo Downloading %BUILD_VS_SVNDIR% libraries, please wait.
+ echo.
+:RETRY
+ "%SVN%" checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR%
+ if errorlevel 1 (
+ set /p LibRetry= "Error during donwload, retry? y/n"
+ if /I "!LibRetry!"=="Y" (
+ cd %BUILD_VS_LIBDIR%
+ "%SVN%" cleanup
+ cd %BLENDER_DIR%
+ goto RETRY
+ )
+ echo.
+ echo Error: Download of external libraries failed.
+ echo This is needed for building, please manually run 'svn cleanup' and 'svn update' in
+ echo %BUILD_VS_LIBDIR% , until this is resolved you CANNOT make a successfull blender build
+ echo.
+ exit /b 1
+ )
+ )
+ )
+)
+
+if NOT EXIST %BUILD_VS_LIBDIR% (
+ echo.
+ echo Error: Required libraries not found at "%BUILD_VS_LIBDIR%"
+ echo This is needed for building, aborting!
+ echo.
+ exit /b 1
+) \ No newline at end of file
diff --git a/build_files/windows/check_spaces_in_path.cmd b/build_files/windows/check_spaces_in_path.cmd
new file mode 100644
index 00000000000..2e9300ae6d5
--- /dev/null
+++ b/build_files/windows/check_spaces_in_path.cmd
@@ -0,0 +1,6 @@
+set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
+
+if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
+ echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
+ exit /b 1
+) \ No newline at end of file
diff --git a/build_files/windows/check_submodules.cmd b/build_files/windows/check_submodules.cmd
new file mode 100644
index 00000000000..c0c64148dd7
--- /dev/null
+++ b/build_files/windows/check_submodules.cmd
@@ -0,0 +1,20 @@
+if NOT exist "%BLENDER_DIR%/source/tools" (
+ echo Checking out sub-modules
+ if not "%GIT%" == "" (
+ "%GIT%" submodule update --init --recursive --progress
+ if errorlevel 1 goto FAIL
+ "%GIT%" submodule foreach git checkout master
+ if errorlevel 1 goto FAIL
+ "%GIT%" submodule foreach git pull --rebase origin master
+ if errorlevel 1 goto FAIL
+ goto EOF
+ ) else (
+ echo Blender submodules not found, and git not found in path to retrieve them.
+ goto FAIL
+ )
+)
+goto EOF
+
+:FAIL
+exit /b 1
+:EOF \ No newline at end of file
diff --git a/build_files/windows/configure_msbuild.cmd b/build_files/windows/configure_msbuild.cmd
new file mode 100644
index 00000000000..135b7933ab2
--- /dev/null
+++ b/build_files/windows/configure_msbuild.cmd
@@ -0,0 +1,59 @@
+set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%WINDOWS_ARCH%" %TESTS_CMAKE_ARGS%
+
+if "%BUILD_ARCH%"=="x64" (
+ set MSBUILD_PLATFORM=x64
+) else if "%BUILD_ARCH%"=="x86" (
+ set MSBUILD_PLATFORM=win32
+)
+
+if NOT EXIST %BUILD_DIR%\nul (
+ mkdir %BUILD_DIR%
+)
+
+if "%MUST_CLEAN%"=="1" (
+ echo Cleaning %BUILD_DIR%
+ msbuild ^
+ %BUILD_DIR%\Blender.sln ^
+ /target:clean ^
+ /property:Configuration=%BUILD_TYPE% ^
+ /verbosity:minimal ^
+ /p:platform=%MSBUILD_PLATFORM%
+)
+
+if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1
+if "%NOBUILD%"=="1" set MUST_CONFIGURE=1
+
+if "%MUST_CONFIGURE%"=="1" (
+
+ if NOT "%verbose%" == "" (
+ echo %CMAKE% %BUILD_CMAKE_ARGS% -H%BLENDER_DIR% -B%BUILD_DIR%
+ )
+
+ cmake ^
+ %BUILD_CMAKE_ARGS% ^
+ -H%BLENDER_DIR% ^
+ -B%BUILD_DIR%
+
+ if %ERRORLEVEL% NEQ 0 (
+ echo "Configuration Failed"
+ exit /b 1
+ )
+)
+
+echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd
+echo "%CMAKE%" . >> %BUILD_DIR%\rebuild.cmd
+echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
+echo msbuild ^
+ %BUILD_DIR%\Blender.sln ^
+ /target:build ^
+ /property:Configuration=%BUILD_TYPE% ^
+ /maxcpucount:2 ^
+ /verbosity:minimal ^
+ /p:platform=%MSBUILD_PLATFORM% ^
+ /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log >> %BUILD_DIR%\rebuild.cmd
+echo msbuild ^
+ %BUILD_DIR%\INSTALL.vcxproj ^
+ /property:Configuration=%BUILD_TYPE% ^
+ /verbosity:minimal ^
+ /p:platform=%MSBUILD_PLATFORM% >> %BUILD_DIR%\rebuild.cmd
+echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd \ No newline at end of file
diff --git a/build_files/windows/configure_ninja.cmd b/build_files/windows/configure_ninja.cmd
new file mode 100644
index 00000000000..13797543bcc
--- /dev/null
+++ b/build_files/windows/configure_ninja.cmd
@@ -0,0 +1,35 @@
+set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Ninja" %TESTS_CMAKE_ARGS% -DCMAKE_BUILD_TYPE=%BUILD_TYPE%
+:DetectionComplete
+if NOT "%verbose%" == "" (
+ echo BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS%
+)
+
+if NOT EXIST %BUILD_DIR%\nul (
+ mkdir %BUILD_DIR%
+)
+
+if "%MUST_CLEAN%"=="1" (
+ echo Cleaning %BUILD_DIR%
+ cd %BUILD_DIR%
+ %CMAKE% cmake --build . --config Clean
+)
+
+if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1
+if "%NOBUILD%"=="1" set MUST_CONFIGURE=1
+
+if "%MUST_CONFIGURE%"=="1" (
+ cmake ^
+ %BUILD_CMAKE_ARGS% ^
+ -H%BLENDER_DIR% ^
+ -B%BUILD_DIR%
+
+ if %ERRORLEVEL% NEQ 0 (
+ echo "Configuration Failed"
+ exit /b 1
+ )
+)
+
+echo call "%VCVARS%" %BUILD_ARCH% > %BUILD_DIR%\rebuild.cmd
+echo echo %%TIME%% ^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd
+echo ninja install >> %BUILD_DIR%\rebuild.cmd
+echo echo %%TIME%% ^>^> buildtime.txt >> %BUILD_DIR%\rebuild.cmd \ No newline at end of file
diff --git a/build_files/windows/detect_architecture.cmd b/build_files/windows/detect_architecture.cmd
new file mode 100644
index 00000000000..cd211668b7f
--- /dev/null
+++ b/build_files/windows/detect_architecture.cmd
@@ -0,0 +1,16 @@
+if "%BUILD_ARCH%"=="" (
+ if "%PROCESSOR_ARCHITECTURE%" == "AMD64" (
+ set WINDOWS_ARCH= Win64
+ set BUILD_ARCH=x64
+ ) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" (
+ set WINDOWS_ARCH= Win64
+ set BUILD_ARCH=x64
+ ) else (
+ set WINDOWS_ARCH=
+ set BUILD_ARCH=x86
+ )
+) else if "%BUILD_ARCH%"=="x64" (
+ set WINDOWS_ARCH= Win64
+) else if "%BUILD_ARCH%"=="x86" (
+ set WINDOWS_ARCH=
+)
diff --git a/build_files/windows/detect_msvc2013.cmd b/build_files/windows/detect_msvc2013.cmd
new file mode 100644
index 00000000000..5688d31c4b6
--- /dev/null
+++ b/build_files/windows/detect_msvc2013.cmd
@@ -0,0 +1,3 @@
+set BUILD_VS_VER=12
+set BUILD_VS_YEAR=2013
+call "%~dp0\detect_msvc_classic.cmd" \ No newline at end of file
diff --git a/build_files/windows/detect_msvc2015.cmd b/build_files/windows/detect_msvc2015.cmd
new file mode 100644
index 00000000000..0818d1dfffc
--- /dev/null
+++ b/build_files/windows/detect_msvc2015.cmd
@@ -0,0 +1,3 @@
+set BUILD_VS_VER=14
+set BUILD_VS_YEAR=2015
+call "%~dp0\detect_msvc_classic.cmd" \ No newline at end of file
diff --git a/build_files/windows/detect_msvc2017.cmd b/build_files/windows/detect_msvc2017.cmd
new file mode 100644
index 00000000000..6a82adb5a4d
--- /dev/null
+++ b/build_files/windows/detect_msvc2017.cmd
@@ -0,0 +1,70 @@
+if NOT "%verbose%" == "" (
+ echo Detecting msvc 2017
+)
+set BUILD_VS_VER=15
+set ProgramFilesX86=%ProgramFiles(x86)%
+if not exist "%ProgramFilesX86%" set ProgramFilesX86=%ProgramFiles%
+
+set vs_where=%ProgramFilesX86%\Microsoft Visual Studio\Installer\vswhere.exe
+if not exist "%vs_where%" (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio 2017 ^(15.2 or newer^) is not detected
+ goto FAIL
+ )
+)
+for /f "usebackq tokens=1* delims=: " %%i in (`"%vs_where%" -latest %VSWHERE_ARGS% -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64`) do (
+ if /i "%%i"=="installationPath" set VS_InstallDir=%%j
+)
+
+if "%VS_InstallDir%"=="" (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio is detected but the "Desktop development with C++" workload has not been instlled
+ goto FAIL
+ )
+)
+
+set VCVARS=%VS_InstallDir%\VC\Auxiliary\Build\vcvarsall.bat
+if exist "%VCVARS%" (
+ call "%VCVARS%" %BUILD_ARCH%
+) else (
+ if NOT "%verbose%" == "" (
+ echo "%VCVARS%" not found
+ )
+ goto FAIL
+)
+
+rem try msbuild
+msbuild /version > NUL
+if errorlevel 1 (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% msbuild not found
+ )
+ goto FAIL
+)
+
+if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% msbuild found
+)
+
+REM try the c++ compiler
+cl 2> NUL 1>&2
+if errorlevel 1 (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler not found
+ )
+ goto FAIL
+)
+
+if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler found
+)
+
+if NOT "%verbose%" == "" (
+ echo Visual Studio 2017 is detected successfully
+)
+goto EOF
+
+:FAIL
+exit /b 1
+
+:EOF
diff --git a/build_files/windows/detect_msvc_classic.cmd b/build_files/windows/detect_msvc_classic.cmd
new file mode 100644
index 00000000000..61bfcf92ddf
--- /dev/null
+++ b/build_files/windows/detect_msvc_classic.cmd
@@ -0,0 +1,69 @@
+if NOT "%verbose%" == "" (
+ echo Detecting msvc %BUILD_VS_YEAR%
+)
+set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
+for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v ProductDir 2^>nul`) DO set MSVC_VC_DIR=%%C
+if DEFINED MSVC_VC_DIR (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% on Win64 detected at "%MSVC_VC_DIR%"
+ )
+ goto msvc_detect_finally
+)
+
+REM Check 32 bits
+set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
+for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v ProductDir 2^>nul`) DO set MSVC_VC_DIR=%%C
+if DEFINED MSVC_VC_DIR (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% on Win32 detected at "%MSVC_VC_DIR%"
+ )
+ goto msvc_detect_finally
+)
+if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% not found.
+)
+goto FAIL
+:msvc_detect_finally
+set VCVARS=%MSVC_VC_DIR%\vcvarsall.bat
+if not exist "%VCVARS%" (
+ echo "%VCVARS%" not found.
+ goto FAIL
+)
+
+call "%vcvars%" %BUILD_ARCH%
+
+rem try msbuild
+msbuild /version > NUL
+if errorlevel 1 (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% msbuild not found
+ )
+ goto FAIL
+)
+
+if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% msbuild found
+)
+
+REM try the c++ compiler
+cl 2> NUL 1>&2
+if errorlevel 1 (
+ if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler not found
+ )
+ goto FAIL
+)
+
+if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% C/C++ Compiler found
+)
+goto DetectionComplete
+
+:FAIL
+exit /b 1
+
+:DetectionComplete
+if NOT "%verbose%" == "" (
+ echo Visual Studio %BUILD_VS_YEAR% Detected successfuly
+)
+exit /b 0
diff --git a/build_files/windows/find_dependencies.cmd b/build_files/windows/find_dependencies.cmd
new file mode 100644
index 00000000000..219e9801831
--- /dev/null
+++ b/build_files/windows/find_dependencies.cmd
@@ -0,0 +1,13 @@
+REM find all dependencies and set the corresponding environement variables.
+for %%X in (svn.exe) do (set SVN=%%~$PATH:X)
+for %%X in (cmake.exe) do (set CMAKE=%%~$PATH:X)
+for %%X in (git.exe) do (set GIT=%%~$PATH:X)
+if NOT "%verbose%" == "" (
+ echo svn : %SVN%
+ echo cmake : %CMAKE%
+ echo git : %GIT%
+)
+if "%CMAKE%" == "" (
+ echo Cmake not found in path, required for building, exiting...
+ exit /b 1
+) \ No newline at end of file
diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd
new file mode 100644
index 00000000000..5a82bf3cf04
--- /dev/null
+++ b/build_files/windows/parse_arguments.cmd
@@ -0,0 +1,78 @@
+set BUILD_DIR=%BLENDER_DIR%..\build_windows
+set BUILD_TYPE=Release
+:argv_loop
+if NOT "%1" == "" (
+
+ REM Help Message
+ if "%1" == "help" (
+ set SHOW_HELP=1
+ goto EOF
+ )
+ REM Build Types
+ if "%1" == "debug" (
+ set BUILD_TYPE=Debug
+ REM Build Configurations
+ ) else if "%1" == "noge" (
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_GAMEENGINE=OFF -DWITH_PLAYER=OFF
+ set BUILD_NGE=_noge
+ ) else if "%1" == "builddir" (
+ set BUILD_DIR_OVERRRIDE="%BLENDER_DIR%..\%2"
+ shift /1
+ ) else if "%1" == "with_tests" (
+ set TESTS_CMAKE_ARGS=-DWITH_GTESTS=On
+ ) else if "%1" == "full" (
+ set TARGET=Full
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
+ -C"%BLENDER_DIR%\build_files\cmake\config\blender_full.cmake"
+ ) else if "%1" == "lite" (
+ set TARGET=Lite
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_lite.cmake"
+ ) else if "%1" == "cycles" (
+ set TARGET=Cycles
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\cycles_standalone.cmake"
+ ) else if "%1" == "headless" (
+ set TARGET=Headless
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\blender_headless.cmake"
+ ) else if "%1" == "bpy" (
+ set TARGET=Bpy
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
+ ) else if "%1" == "release" (
+ set TARGET=Release
+ ) else if "%1" == "x86" (
+ set BUILD_ARCH=x86
+ ) else if "%1" == "x64" (
+ set BUILD_ARCH=x64
+ ) else if "%1" == "2017" (
+ set BUILD_VS_YEAR=2017
+ ) else if "%1" == "2017pre" (
+ set BUILD_VS_YEAR=2017
+ set VSWHERE_ARGS=-prerelease
+ ) else if "%1" == "2015" (
+ set BUILD_VS_YEAR=2015
+ ) else if "%1" == "2013" (
+ set BUILD_VS_YEAR=2013
+ ) else if "%1" == "packagename" (
+ set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
+ shift /1
+ ) else if "%1" == "nobuild" (
+ set NOBUILD=1
+ ) else if "%1" == "showhash" (
+ SET BUILD_SHOW_HASHES=1
+ REM Non-Build Commands
+ ) else if "%1" == "update" (
+ SET BUILD_UPDATE=1
+ ) else if "%1" == "ninja" (
+ SET BUILD_WITH_NINJA=1
+ ) else if "%1" == "clean" (
+ set MUST_CLEAN=1
+ ) else if "%1" == "verbose" (
+ set VERBOSE=1
+ ) else (
+ echo Command "%1" unknown, aborting!
+ exit /b 1
+ )
+ shift /1
+ goto argv_loop
+)
+:EOF
+exit /b 0 \ No newline at end of file
diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd
new file mode 100644
index 00000000000..34af3ff9389
--- /dev/null
+++ b/build_files/windows/reset_variables.cmd
@@ -0,0 +1,23 @@
+rem reset all variables so they do not get accidentally get carried over from previous builds
+set BUILD_DIR_OVERRRIDE=
+set BUILD_CMAKE_ARGS=
+set BUILD_ARCH=
+set BUILD_VS_VER=
+set BUILD_VS_YEAR=
+set BUILD_VS_LIBDIRPOST=
+set BUILD_VS_LIBDIR=
+set BUILD_VS_SVNDIR=
+set BUILD_NGE=
+set KEY_NAME=
+set MSBUILD_PLATFORM=
+set MUST_CLEAN=
+set NOBUILD=
+set TARGET=
+set VERBOSE=
+set WINDOWS_ARCH=
+set TESTS_CMAKE_ARGS=
+set VSWHERE_ARGS=
+set BUILD_UPDATE=
+set BUILD_SHOW_HASHES=
+set SHOW_HELP=
+set BUILD_WITH_NINJA=
diff --git a/build_files/windows/set_build_dir.cmd b/build_files/windows/set_build_dir.cmd
new file mode 100644
index 00000000000..8842a52eb5b
--- /dev/null
+++ b/build_files/windows/set_build_dir.cmd
@@ -0,0 +1,4 @@
+set BUILD_DIR=%BUILD_DIR%_%TARGET%%BUILD_NGE%_%BUILD_ARCH%_vc%BUILD_VS_VER%_%BUILD_TYPE%
+if NOT "%BUILD_DIR_OVERRRIDE%"=="" (
+ set BUILD_DIR=%BUILD_DIR_OVERRRIDE%
+) \ No newline at end of file
diff --git a/build_files/windows/show_hashes.cmd b/build_files/windows/show_hashes.cmd
new file mode 100644
index 00000000000..ff036733946
--- /dev/null
+++ b/build_files/windows/show_hashes.cmd
@@ -0,0 +1,12 @@
+if "%GIT%" == "" (
+ echo Git not found, cannot show hashes.
+ goto EOF
+)
+cd "%BLENDER_DIR%"
+for /f "delims=" %%i in ('%GIT% rev-parse HEAD') do echo Branch_hash=%%i
+cd "%BLENDER_DIR%/release/datafiles/locale"
+for /f "delims=" %%i in ('%GIT% rev-parse HEAD') do echo Locale_hash=%%i
+cd "%BLENDER_DIR%/release/scripts/addons"
+for /f "delims=" %%i in ('%GIT% rev-parse HEAD') do echo Addons_Hash=%%i
+cd "%BLENDER_DIR%"
+:EOF \ No newline at end of file
diff --git a/build_files/windows/show_help.cmd b/build_files/windows/show_help.cmd
new file mode 100644
index 00000000000..0524e8a84fc
--- /dev/null
+++ b/build_files/windows/show_help.cmd
@@ -0,0 +1,29 @@
+echo.
+echo Convenience targets
+echo - release ^(identical to the official blender.org builds^)
+echo - full ^(same as release minus the cuda kernels^)
+echo - lite
+echo - headless
+echo - cycles
+echo - bpy
+echo.
+echo Utilities ^(not associated with building^)
+echo - clean ^(Target must be set^)
+echo - update
+echo - nobuild ^(only generate project files^)
+echo - showhash ^(Show git hashes of source tree^)
+echo.
+echo Configuration options
+echo - verbose ^(enable diagnostic output during configuration^)
+echo - with_tests ^(enable building unit tests^)
+echo - noge ^(disable building game enginge and player^)
+echo - debug ^(Build an unoptimized debuggable build^)
+echo - packagename [newname] ^(override default cpack package name^)
+echo - buildir [newdir] ^(override default build folder^)
+echo - x86 ^(override host auto-detect and build 32 bit code^)
+echo - x64 ^(override host auto-detect and build 64 bit code^)
+echo - 2013 ^(build with visual studio 2013^)
+echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
+echo - 2017 ^(build with visual studio 2017^) [EXPERIMENTAL]
+echo - 2017pre ^(build with visual studio 2017 pre-release^) [EXPERIMENTAL]
+echo.
diff --git a/build_files/windows/update_sources.cmd b/build_files/windows/update_sources.cmd
new file mode 100644
index 00000000000..22d93fabb95
--- /dev/null
+++ b/build_files/windows/update_sources.cmd
@@ -0,0 +1,16 @@
+if "%SVN%" == "" (
+ echo svn not found, cannot update libraries
+ goto UPDATE_GIT
+)
+"%SVN%" up "%BLENDER_DIR%/../lib/*"
+
+:UPDATE_GIT
+
+if "%GIT%" == "" (
+ echo Git not found, cannot update code
+ goto EOF
+)
+"%GIT%" pull --rebase
+"%GIT%" submodule foreach git pull --rebase origin master
+
+:EOF \ No newline at end of file
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index cc2a6824190..15d633b5c9a 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -811,6 +811,19 @@ static ShaderNode *add_node(Scene *scene,
get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
node = sky;
}
+ else if(b_node.is_a(&RNA_ShaderNodeTexIES)) {
+ BL::ShaderNodeTexIES b_ies_node(b_node);
+ IESLightNode *ies = new IESLightNode();
+ switch(b_ies_node.mode()) {
+ case BL::ShaderNodeTexIES::mode_EXTERNAL:
+ ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
+ break;
+ case BL::ShaderNodeTexIES::mode_INTERNAL:
+ ies->ies = get_text_datablock_content(b_ies_node.ies().ptr);
+ break;
+ }
+ node = ies;
+ }
else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
NormalMapNode *nmap = new NormalMapNode();
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index a8379914b83..983988f4e36 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -468,6 +468,21 @@ static inline string blender_absolute_path(BL::BlendData& b_data,
return path;
}
+static inline string get_text_datablock_content(const PointerRNA&& ptr)
+{
+ if(ptr.data == NULL) {
+ return "";
+ }
+
+ string content;
+ BL::Text::lines_iterator iter;
+ for(iter.begin(ptr); iter; ++iter) {
+ content += iter->body() + "\n";
+ }
+
+ return content;
+}
+
/* Texture Space */
static inline void mesh_texture_space(BL::Mesh& b_mesh,
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index 7d46e31ce24..15d34a79bb8 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -73,12 +73,13 @@ struct SocketType
INTERNAL = (1 << 2) | (1 << 3),
LINK_TEXTURE_GENERATED = (1 << 4),
- LINK_TEXTURE_UV = (1 << 5),
- LINK_INCOMING = (1 << 6),
- LINK_NORMAL = (1 << 7),
- LINK_POSITION = (1 << 8),
- LINK_TANGENT = (1 << 9),
- DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9)
+ LINK_TEXTURE_NORMAL = (1 << 5),
+ LINK_TEXTURE_UV = (1 << 6),
+ LINK_INCOMING = (1 << 7),
+ LINK_NORMAL = (1 << 8),
+ LINK_POSITION = (1 << 9),
+ LINK_TANGENT = (1 << 10),
+ DEFAULT_LINK_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10)
};
ustring name;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 9b7f4e00084..457602ae4e7 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -178,6 +178,7 @@ set(SRC_SVM_HEADERS
svm/svm_geometry.h
svm/svm_gradient.h
svm/svm_hsv.h
+ svm/svm_ies.h
svm/svm_image.h
svm/svm_invert.h
svm/svm_light_path.h
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index cd879e27e72..b1be0b2155a 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -224,7 +224,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float
float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res);
/* importance-sampled V direction */
- float dv = (randv - cdf_v.y) / (cdf_next_v.y - cdf_v.y);
+ float dv = inverse_lerp(cdf_v.y, cdf_next_v.y, randv);
float v = (index_v + dv) / res;
/* this is basically std::lower_bound as used by pbrt */
@@ -250,7 +250,7 @@ float3 background_map_sample(KernelGlobals *kg, float randu, float randv, float
float2 cdf_last_u = kernel_tex_fetch(__light_background_conditional_cdf, index_v * cdf_count + res);
/* importance-sampled U direction */
- float du = (randu - cdf_u.y) / (cdf_next_u.y - cdf_u.y);
+ float du = inverse_lerp(cdf_u.y, cdf_next_u.y, randu);
float u = (index_u + du) / res;
/* compute pdf */
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 9047b93a0b2..a7b8c492ee9 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -81,5 +81,8 @@ KERNEL_TEX(uint, __sobol_directions)
/* image textures */
KERNEL_TEX(TextureInfo, __texture_info)
+/* ies lights */
+KERNEL_TEX(float, __ies)
+
#undef KERNEL_TEX
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 0c5e5e30e47..32d86b7192a 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -956,9 +956,15 @@ bool OSLRenderServices::texture(ustring filename,
status = true;
}
}
+ else if(filename[1] == 'l') {
+ /* IES light. */
+ int slot = atoi(filename.c_str() + 2);
+ result[0] = kernel_ies_interp(kg, slot, s, t);
+ status = true;
+ }
else {
/* Packed texture. */
- int slot = atoi(filename.c_str() + 1);
+ int slot = atoi(filename.c_str() + 2);
float4 rgba = kernel_tex_image_interp(kg, slot, s, 1.0f - t);
result[0] = rgba[0];
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 6ec651a96d8..b28d017c1c2 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC_OSL
node_principled_volume.osl
node_holdout.osl
node_hsv.osl
+ node_ies_light.osl
node_image_texture.osl
node_invert.osl
node_layer_weight.osl
diff --git a/intern/cycles/kernel/shaders/node_ies_light.osl b/intern/cycles/kernel/shaders/node_ies_light.osl
new file mode 100644
index 00000000000..a0954e3a444
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_ies_light.osl
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdosl.h"
+#include "node_texture.h"
+
+/* IES Light */
+
+shader node_ies_light(
+ int use_mapping = 0,
+ matrix mapping = matrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+ int slot = 0,
+ float Strength = 1.0,
+ point Vector = I,
+ output float Fac = 0.0)
+{
+ point p = Vector;
+
+ if (use_mapping) {
+ p = transform(mapping, p);
+ }
+
+ p = normalize(p);
+
+ float v_angle = acos(-p[2]);
+ float h_angle = atan2(p[0], p[1]) + M_PI;
+
+ Fac = Strength * texture(format("@l%d", slot), h_angle, v_angle);
+}
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 39cd5da7b12..bfa146f2d93 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -157,6 +157,7 @@ CCL_NAMESPACE_END
#include "kernel/svm/svm_camera.h"
#include "kernel/svm/svm_geometry.h"
#include "kernel/svm/svm_hsv.h"
+#include "kernel/svm/svm_ies.h"
#include "kernel/svm/svm_image.h"
#include "kernel/svm/svm_gamma.h"
#include "kernel/svm/svm_brightness.h"
@@ -421,6 +422,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
case NODE_LIGHT_FALLOFF:
svm_node_light_falloff(sd, stack, node);
break;
+ case NODE_IES:
+ svm_node_ies(kg, sd, stack, node, &offset);
+ break;
# endif /* __EXTRA_NODES__ */
#endif /* NODES_GROUP(NODE_GROUP_LEVEL_2) */
diff --git a/intern/cycles/kernel/svm/svm_ies.h b/intern/cycles/kernel/svm/svm_ies.h
new file mode 100644
index 00000000000..6130c3348b0
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_ies.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2011-2013 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* IES Light */
+
+ccl_device_inline float interpolate_ies_vertical(KernelGlobals *kg, int ofs, int v, int v_num, float v_frac, int h)
+{
+ /* Since lookups are performed in spherical coordinates, clamping the coordinates at the low end of v
+ * (corresponding to the north pole) would result in artifacts.
+ * The proper way of dealing with this would be to lookup the corresponding value on the other side of the pole,
+ * but since the horizontal coordinates might be nonuniform, this would require yet another interpolation.
+ * Therefore, the assumtion is made that the light is going to be symmetrical, which means that we can just take
+ * the corresponding value at the current horizontal coordinate. */
+
+#define IES_LOOKUP(v) kernel_tex_fetch(__ies, ofs+h*v_num+(v))
+ /* If v is zero, assume symmetry and read at v=1 instead of v=-1. */
+ float a = IES_LOOKUP((v == 0)? 1 : v-1);
+ float b = IES_LOOKUP(v);
+ float c = IES_LOOKUP(v+1);
+ float d = IES_LOOKUP(min(v+2, v_num-1));
+#undef IES_LOOKUP
+
+ return cubic_interp(a, b, c, d, v_frac);
+}
+
+ccl_device_inline float kernel_ies_interp(KernelGlobals *kg, int slot, float h_angle, float v_angle)
+{
+ /* Find offset of the IES data in the table. */
+ int ofs = __float_as_int(kernel_tex_fetch(__ies, slot));
+ if(ofs == -1) {
+ return 100.0f;
+ }
+
+ int h_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
+ int v_num = __float_as_int(kernel_tex_fetch(__ies, ofs++));
+
+#define IES_LOOKUP_ANGLE_H(h) kernel_tex_fetch(__ies, ofs+(h))
+#define IES_LOOKUP_ANGLE_V(v) kernel_tex_fetch(__ies, ofs+h_num+(v))
+
+ /* Check whether the angle is within the bounds of the IES texture. */
+ if(v_angle >= IES_LOOKUP_ANGLE_V(v_num-1)) {
+ return 0.0f;
+ }
+ kernel_assert(v_angle >= IES_LOOKUP_ANGLE_V(0));
+ kernel_assert(h_angle >= IES_LOOKUP_ANGLE_H(0));
+ kernel_assert(h_angle <= IES_LOOKUP_ANGLE_H(h_num-1));
+
+ /* Lookup the angles to find the table position. */
+ int h_i, v_i;
+ /* TODO(lukas): Consider using bisection. Probably not worth it for the vast majority of IES files. */
+ for(h_i = 0; IES_LOOKUP_ANGLE_H(h_i+1) < h_angle; h_i++);
+ for(v_i = 0; IES_LOOKUP_ANGLE_V(v_i+1) < v_angle; v_i++);
+
+ float h_frac = inverse_lerp(IES_LOOKUP_ANGLE_H(h_i), IES_LOOKUP_ANGLE_H(h_i+1), h_angle);
+ float v_frac = inverse_lerp(IES_LOOKUP_ANGLE_V(v_i), IES_LOOKUP_ANGLE_V(v_i+1), v_angle);
+
+#undef IES_LOOKUP_ANGLE_H
+#undef IES_LOOKUP_ANGLE_V
+
+ /* Skip forward to the actual intensity data. */
+ ofs += h_num+v_num;
+
+ /* Perform cubic interpolation along the horizontal coordinate to get the intensity value.
+ * If h_i is zero, just wrap around since the horizontal angles always go over the full circle.
+ * However, the last entry (360°) equals the first one, so we need to wrap around to the one before that. */
+ float a = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i == 0)? h_num-2 : h_i-1);
+ float b = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i);
+ float c = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, h_i+1);
+ /* Same logic here, wrap around to the second element if necessary. */
+ float d = interpolate_ies_vertical(kg, ofs, v_i, v_num, v_frac, (h_i+2 == h_num)? 1 : h_i+2);
+
+ /* Cubic interpolation can result in negative values, so get rid of them. */
+ return max(cubic_interp(a, b, c, d, h_frac), 0.0f);
+}
+
+ccl_device void svm_node_ies(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
+{
+ uint vector_offset, strength_offset, fac_offset, dummy, slot = node.z;
+ decode_node_uchar4(node.y, &strength_offset, &vector_offset, &fac_offset, &dummy);
+
+ float3 vector = stack_load_float3(stack, vector_offset);
+ float strength = stack_load_float_default(stack, strength_offset, node.w);
+
+ vector = normalize(vector);
+ float v_angle = safe_acosf(-vector.z);
+ float h_angle = atan2f(vector.x, vector.y) + M_PI_F;
+
+ float fac = strength * kernel_ies_interp(kg, slot, h_angle, v_angle);
+
+ if(stack_valid(fac_offset)) {
+ stack_store_float(stack, fac_offset, fac);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index dc62e25b340..ac24d23ecd2 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -136,6 +136,7 @@ typedef enum ShaderNodeType {
NODE_DISPLACEMENT,
NODE_VECTOR_DISPLACEMENT,
NODE_PRINCIPLED_VOLUME,
+ NODE_IES,
} ShaderNodeType;
typedef enum NodeAttributeType {
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 096de878e51..59e1a12c3a1 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -774,6 +774,12 @@ void ShaderGraph::default_inputs(bool do_osl)
connect(texco->output("Generated"), input);
}
+ if(input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
+ if(!texco)
+ texco = new TextureCoordinateNode();
+
+ connect(texco->output("Normal"), input);
+ }
else if(input->flags() & SocketType::LINK_TEXTURE_UV) {
if(!texco)
texco = new TextureCoordinateNode();
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 01a8b50cb21..91f9b4e3bec 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -25,6 +25,8 @@
#include "render/shader.h"
#include "util/util_foreach.h"
+#include "util/util_hash.h"
+#include "util/util_path.h"
#include "util/util_progress.h"
#include "util/util_logging.h"
@@ -176,6 +178,9 @@ LightManager::LightManager()
LightManager::~LightManager()
{
+ foreach(IESSlot *slot, ies_slots) {
+ delete slot;
+ }
}
bool LightManager::has_background_light(Scene *scene)
@@ -865,6 +870,9 @@ void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *sce
device_update_background(device, dscene, scene, progress);
if(progress.get_cancel()) return;
+ device_update_ies(dscene);
+ if(progress.get_cancel()) return;
+
if(use_light_visibility != scene->film->use_light_visibility) {
scene->film->use_light_visibility = use_light_visibility;
scene->film->tag_update(scene);
@@ -879,6 +887,7 @@ void LightManager::device_free(Device *, DeviceScene *dscene)
dscene->lights.free();
dscene->light_background_marginal_cdf.free();
dscene->light_background_conditional_cdf.free();
+ dscene->ies_lights.free();
}
void LightManager::tag_update(Scene * /*scene*/)
@@ -886,5 +895,118 @@ void LightManager::tag_update(Scene * /*scene*/)
need_update = true;
}
+int LightManager::add_ies_from_file(ustring filename)
+{
+ string content;
+ /* If the file can't be opened, call with an empty string */
+ path_read_text(filename.c_str(), content);
+
+ return add_ies(ustring(content));
+}
+
+int LightManager::add_ies(ustring content)
+{
+ uint hash = hash_string(content.c_str());
+
+ thread_scoped_lock ies_lock(ies_mutex);
+
+ /* Check whether this IES already has a slot. */
+ size_t slot;
+ for(slot = 0; slot < ies_slots.size(); slot++) {
+ if(ies_slots[slot]->hash == hash) {
+ ies_slots[slot]->users++;
+ return slot;
+ }
+ }
+
+ /* Try to find an empty slot for the new IES. */
+ for(slot = 0; slot < ies_slots.size(); slot++) {
+ if(ies_slots[slot]->users == 0 && ies_slots[slot]->hash == 0) {
+ break;
+ }
+ }
+
+ /* If there's no free slot, add one. */
+ if(slot == ies_slots.size()) {
+ ies_slots.push_back(new IESSlot());
+ }
+
+ ies_slots[slot]->ies.load(content);
+ ies_slots[slot]->users = 1;
+ ies_slots[slot]->hash = hash;
+
+ need_update = true;
+
+ return slot;
+}
+
+void LightManager::remove_ies(int slot)
+{
+ thread_scoped_lock ies_lock(ies_mutex);
+
+ if(slot < 0 || slot >= ies_slots.size()) {
+ assert(false);
+ return;
+ }
+
+ assert(ies_slots[slot]->users > 0);
+ ies_slots[slot]->users--;
+
+ /* If the slot has no more users, update the device to remove it. */
+ need_update |= (ies_slots[slot]->users == 0);
+}
+
+void LightManager::device_update_ies(DeviceScene *dscene)
+{
+ /* Clear empty slots. */
+ foreach(IESSlot *slot, ies_slots) {
+ if(slot->users == 0) {
+ slot->hash = 0;
+ slot->ies.clear();
+ }
+ }
+
+ /* Shrink the slot table by removing empty slots at the end. */
+ int slot_end;
+ for(slot_end = ies_slots.size(); slot_end; slot_end--) {
+ if(ies_slots[slot_end-1]->users > 0) {
+ /* If the preceding slot has users, we found the new end of the table. */
+ break;
+ }
+ else {
+ /* The slot will be past the new end of the table, so free it. */
+ delete ies_slots[slot_end-1];
+ }
+ }
+ ies_slots.resize(slot_end);
+
+ if(ies_slots.size() > 0) {
+ int packed_size = 0;
+ foreach(IESSlot *slot, ies_slots) {
+ packed_size += slot->ies.packed_size();
+ }
+
+ /* ies_lights starts with an offset table that contains the offset of every slot,
+ * or -1 if the slot is invalid.
+ * Following that table, the packed valid IES lights are stored. */
+ float *data = dscene->ies_lights.alloc(ies_slots.size() + packed_size);
+
+ int offset = ies_slots.size();
+ for(int i = 0; i < ies_slots.size(); i++) {
+ int size = ies_slots[i]->ies.packed_size();
+ if(size > 0) {
+ data[i] = __int_as_float(offset);
+ ies_slots[i]->ies.pack(data + offset);
+ offset += size;
+ }
+ else {
+ data[i] = __int_as_float(-1);
+ }
+ }
+
+ dscene->ies_lights.copy_to_device();
+ }
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 539a33f4e41..acbbdd15ddf 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -21,6 +21,8 @@
#include "graph/node.h"
+#include "util/util_ies.h"
+#include "util/util_thread.h"
#include "util/util_types.h"
#include "util/util_vector.h"
@@ -87,6 +89,11 @@ public:
LightManager();
~LightManager();
+ /* IES texture management */
+ int add_ies(ustring ies);
+ int add_ies_from_file(ustring filename);
+ void remove_ies(int slot);
+
void device_update(Device *device,
DeviceScene *dscene,
Scene *scene,
@@ -116,9 +123,19 @@ protected:
DeviceScene *dscene,
Scene *scene,
Progress& progress);
+ void device_update_ies(DeviceScene *dscene);
/* Check whether light manager can use the object as a light-emissive. */
bool object_usable_as_light(Object *object);
+
+ struct IESSlot {
+ IESFile ies;
+ uint hash;
+ int users;
+ };
+
+ vector<IESSlot*> ies_slots;
+ thread_mutex ies_mutex;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index c468924fa66..3dad4d1a346 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -16,6 +16,7 @@
#include "render/image.h"
#include "render/integrator.h"
+#include "render/light.h"
#include "render/nodes.h"
#include "render/scene.h"
#include "render/svm.h"
@@ -384,10 +385,10 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
/* TODO(sergey): It's not so simple to pass custom attribute
* to the texture() function in order to make builtin images
* support more clear. So we use special file name which is
- * "@<slot_number>" and check whether file name matches this
+ * "@i<slot_number>" and check whether file name matches this
* mask in the OSLRenderServices::texture().
*/
- compiler.parameter("filename", string_printf("@%d", slot).c_str());
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
}
if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
compiler.parameter("color_space", "linear");
@@ -567,7 +568,7 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
compiler.parameter(this, "filename");
}
else {
- compiler.parameter("filename", string_printf("@%d", slot).c_str());
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
}
compiler.parameter(this, "projection");
if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
@@ -954,6 +955,97 @@ void VoronoiTextureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_voronoi_texture");
}
+/* IES Light */
+
+NODE_DEFINE(IESLightNode)
+{
+ NodeType* type = NodeType::add("ies_light", create, NodeType::SHADER);
+
+ TEXTURE_MAPPING_DEFINE(IESLightNode);
+
+ SOCKET_STRING(ies, "IES", ustring());
+ SOCKET_STRING(filename, "File Name", ustring());
+
+ SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
+ SOCKET_IN_POINT(vector, "Vector", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TEXTURE_NORMAL);
+
+ SOCKET_OUT_FLOAT(fac, "Fac");
+
+ return type;
+}
+
+IESLightNode::IESLightNode()
+: TextureNode(node_type)
+{
+ light_manager = NULL;
+ slot = -1;
+}
+
+ShaderNode *IESLightNode::clone() const
+{
+ IESLightNode *node = new IESLightNode(*this);
+
+ node->light_manager = NULL;
+ node->slot = -1;
+
+ return node;
+}
+
+IESLightNode::~IESLightNode()
+{
+ if(light_manager) {
+ light_manager->remove_ies(slot);
+ }
+}
+
+void IESLightNode::get_slot()
+{
+ assert(light_manager);
+
+ if(slot == -1) {
+ if(ies.empty()) {
+ slot = light_manager->add_ies_from_file(filename);
+ }
+ else {
+ slot = light_manager->add_ies(ies);
+ }
+ }
+}
+
+void IESLightNode::compile(SVMCompiler& compiler)
+{
+ light_manager = compiler.light_manager;
+ get_slot();
+
+ ShaderInput *strength_in = input("Strength");
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *fac_out = output("Fac");
+
+ int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
+
+ compiler.add_node(NODE_IES,
+ compiler.encode_uchar4(
+ compiler.stack_assign_if_linked(strength_in),
+ vector_offset,
+ compiler.stack_assign(fac_out),
+ 0),
+ slot,
+ __float_as_int(strength));
+
+ tex_mapping.compile_end(compiler, vector_in, vector_offset);
+}
+
+void IESLightNode::compile(OSLCompiler& compiler)
+{
+ light_manager = compiler.light_manager;
+ get_slot();
+
+ tex_mapping.compile(compiler);
+
+ compiler.parameter("slot", slot);
+ compiler.add(this, "node_ies_light");
+}
+
/* Musgrave Texture */
NODE_DEFINE(MusgraveTextureNode)
@@ -1470,7 +1562,7 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler)
}
if(slot != -1) {
- compiler.parameter("filename", string_printf("@%d", slot).c_str());
+ compiler.parameter("filename", string_printf("@i%d", slot).c_str());
}
if(space == NODE_TEX_VOXEL_SPACE_WORLD) {
compiler.parameter("mapping", tfm);
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index 58c3d472cd3..35a7df690c3 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -25,6 +25,7 @@
CCL_NAMESPACE_BEGIN
class ImageManager;
+class LightManager;
class Scene;
class Shader;
@@ -281,6 +282,27 @@ public:
}
};
+class IESLightNode : public TextureNode {
+public:
+ SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
+
+ ~IESLightNode();
+ ShaderNode *clone() const;
+ virtual int get_group() { return NODE_GROUP_LEVEL_2; }
+
+ ustring filename;
+ ustring ies;
+
+ float strength;
+ float3 vector;
+
+private:
+ LightManager *light_manager;
+ int slot;
+
+ void get_slot();
+};
+
class MappingNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MappingNode)
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index f1a22350060..dde622bff8a 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -99,7 +99,9 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
* compile shaders alternating */
thread_scoped_lock lock(ss_mutex);
- OSLCompiler compiler((void*)this, (void*)ss, scene->image_manager);
+ OSLCompiler compiler((void*)this, (void*)ss,
+ scene->image_manager,
+ scene->light_manager);
compiler.background = (shader == scene->default_background);
compiler.compile(scene, og, shader);
@@ -546,11 +548,14 @@ OSLNode *OSLShaderManager::osl_node(const std::string& filepath,
/* Graph Compiler */
-OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_, ImageManager *image_manager_)
+OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_,
+ ImageManager *image_manager_,
+ LightManager *light_manager_)
{
manager = manager_;
shadingsys = shadingsys_;
image_manager = image_manager_;
+ light_manager = light_manager_;
current_type = SHADER_TYPE_SURFACE;
current_shader = NULL;
background = false;
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 95e35dd857b..7a3208c402a 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -120,7 +120,9 @@ protected:
class OSLCompiler {
public:
- OSLCompiler(void *manager, void *shadingsys, ImageManager *image_manager);
+ OSLCompiler(void *manager, void *shadingsys,
+ ImageManager *image_manager,
+ LightManager *light_manager);
void compile(Scene *scene, OSLGlobals *og, Shader *shader);
void add(ShaderNode *node, const char *name, bool isfilepath = false);
@@ -146,6 +148,7 @@ public:
bool background;
ImageManager *image_manager;
+ LightManager *light_manager;
private:
#ifdef WITH_OSL
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index ba47e3ab6f8..b35cdbd3db5 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -76,7 +76,8 @@ DeviceScene::DeviceScene(Device *device)
svm_nodes(device, "__svm_nodes", MEM_TEXTURE),
shaders(device, "__shaders", MEM_TEXTURE),
lookup_table(device, "__lookup_table", MEM_TEXTURE),
- sobol_directions(device, "__sobol_directions", MEM_TEXTURE)
+ sobol_directions(device, "__sobol_directions", MEM_TEXTURE),
+ ies_lights(device, "__ies", MEM_TEXTURE)
{
memset(&data, 0, sizeof(data));
}
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 04bd4735a86..6c67433c9fc 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -119,6 +119,9 @@ public:
/* integrator */
device_vector<uint> sobol_directions;
+ /* ies lights */
+ device_vector<float> ies_lights;
+
KernelData data;
DeviceScene(Device *device);
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index c5b4060d5c3..eb8a35a271f 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -58,7 +58,7 @@ void SVMShaderManager::device_update_shader(Scene *scene,
svm_nodes.push_back_slow(make_int4(NODE_SHADER_JUMP, 0, 0, 0));
SVMCompiler::Summary summary;
- SVMCompiler compiler(scene->shader_manager, scene->image_manager);
+ SVMCompiler compiler(scene->shader_manager, scene->image_manager, scene->light_manager);
compiler.background = (shader == scene->default_background);
compiler.compile(scene, shader, svm_nodes, 0, &summary);
@@ -154,10 +154,13 @@ void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *s
/* Graph Compiler */
-SVMCompiler::SVMCompiler(ShaderManager *shader_manager_, ImageManager *image_manager_)
+SVMCompiler::SVMCompiler(ShaderManager *shader_manager_,
+ ImageManager *image_manager_,
+ LightManager *light_manager_)
{
shader_manager = shader_manager_;
image_manager = image_manager_;
+ light_manager = light_manager_;
max_stack_use = 0;
current_type = SHADER_TYPE_SURFACE;
current_shader = NULL;
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index 18be0fa9a22..7cf1e4ad791 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -95,7 +95,9 @@ public:
string full_report() const;
};
- SVMCompiler(ShaderManager *shader_manager, ImageManager *image_manager);
+ SVMCompiler(ShaderManager *shader_manager,
+ ImageManager *image_manager,
+ LightManager *light_manager);
void compile(Scene *scene,
Shader *shader,
array<int4>& svm_nodes,
@@ -125,6 +127,7 @@ public:
ImageManager *image_manager;
ShaderManager *shader_manager;
+ LightManager *light_manager;
bool background;
protected:
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 24043e2231b..3b690860d53 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -11,6 +11,7 @@ set(INC_SYS
set(SRC
util_aligned_malloc.cpp
util_debug.cpp
+ util_ies.cpp
util_logging.cpp
util_math_cdf.cpp
util_md5.cpp
@@ -45,6 +46,7 @@ set(SRC_HEADERS
util_guarded_allocator.h
util_half.h
util_hash.h
+ util_ies.h
util_image.h
util_image_impl.h
util_list.h
diff --git a/intern/cycles/util/util_ies.cpp b/intern/cycles/util/util_ies.cpp
new file mode 100644
index 00000000000..4824c886609
--- /dev/null
+++ b/intern/cycles/util/util_ies.cpp
@@ -0,0 +1,392 @@
+/*
+ * Copyright 2011-2018 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "util/util_foreach.h"
+#include "util/util_ies.h"
+#include "util/util_math.h"
+#include "util/util_string.h"
+
+CCL_NAMESPACE_BEGIN
+
+bool IESFile::load(ustring ies)
+{
+ clear();
+ if(!parse(ies) || !process()) {
+ clear();
+ return false;
+ }
+ return true;
+}
+
+void IESFile::clear()
+{
+ intensity.clear();
+ v_angles.clear();
+ h_angles.clear();
+}
+
+int IESFile::packed_size()
+{
+ if(v_angles.size() && h_angles.size() > 0) {
+ return 2 + h_angles.size() + v_angles.size() + h_angles.size()*v_angles.size();
+ }
+ return 0;
+}
+
+void IESFile::pack(float *data)
+{
+ if(v_angles.size() && h_angles.size()) {
+ *(data++) = __int_as_float(h_angles.size());
+ *(data++) = __int_as_float(v_angles.size());
+
+ memcpy(data, &h_angles[0], h_angles.size()*sizeof(float));
+ data += h_angles.size();
+ memcpy(data, &v_angles[0], v_angles.size()*sizeof(float));
+ data += v_angles.size();
+
+ for(int h = 0; h < intensity.size(); h++) {
+ memcpy(data, &intensity[h][0], v_angles.size()*sizeof(float));
+ data += v_angles.size();
+ }
+ }
+}
+
+class IESTextParser {
+public:
+ vector<char> text;
+ char *data;
+
+ IESTextParser(ustring str)
+ : text(str.begin(), str.end())
+ {
+ std::replace(text.begin(), text.end(), ',', ' ');
+ data = strstr(&text[0], "\nTILT=");
+ }
+
+ bool eof() {
+ return (data == NULL) || (data[0] == '\0');
+ }
+
+ double get_double() {
+ if(eof()) {
+ return 0.0;
+ }
+ char *old_data = data;
+ double val = strtod(data, &data);
+ if(data == old_data) {
+ data = NULL;
+ return 0.0;
+ }
+ return val;
+ }
+
+ long get_long() {
+ if(eof()) {
+ return 0;
+ }
+ char *old_data = data;
+ long val = strtol(data, &data, 10);
+ if(data == old_data) {
+ data = NULL;
+ return 0;
+ }
+ return val;
+ }
+};
+
+bool IESFile::parse(ustring ies)
+{
+ IESTextParser parser(ies);
+ if(parser.eof()) {
+ return false;
+ }
+
+ /* Handle the tilt data block. */
+ if(strncmp(parser.data, "\nTILT=INCLUDE", 13) == 0) {
+ parser.data += 13;
+ parser.get_double(); /* Lamp to Luminaire geometry */
+ int num_tilt = parser.get_long(); /* Amount of tilt angles and factors */
+ /* Skip over angles and factors. */
+ for(int i = 0; i < 2*num_tilt; i++) {
+ parser.get_double();
+ }
+ }
+ else {
+ /* Skip to next line. */
+ parser.data = strstr(parser.data+1, "\n");
+ }
+
+ if(parser.eof()) {
+ return false;
+ }
+ parser.data++;
+
+ parser.get_long(); /* Number of lamps */
+ parser.get_double(); /* Lumens per lamp */
+ double factor = parser.get_double(); /* Candela multiplier */
+ int v_angles_num = parser.get_long(); /* Number of vertical angles */
+ int h_angles_num = parser.get_long(); /* Number of horizontal angles */
+ type = (IESType) parser.get_long(); /* Photometric type */
+
+ /* TODO(lukas): Test whether the current type B processing can also deal with type A files.
+ * In theory the only difference should be orientation which we ignore anyways, but with IES you never know...
+ */
+ if(type != TYPE_B && type != TYPE_C) {
+ return false;
+ }
+
+ parser.get_long(); /* Unit of the geometry data */
+ parser.get_double(); /* Width */
+ parser.get_double(); /* Length */
+ parser.get_double(); /* Height */
+ factor *= parser.get_double(); /* Ballast factor */
+ factor *= parser.get_double(); /* Ballast-Lamp Photometric factor */
+ parser.get_double(); /* Input Watts */
+
+ /* Intensity values in IES files are specified in candela (lumen/sr), a photometric quantity.
+ * Cycles expects radiometric quantities, though, which requires a conversion.
+ * However, the Luminous efficacy (ratio of lumens per Watt) depends on the spectral distribution
+ * of the light source since lumens take human perception into account.
+ * Since this spectral distribution is not known from the IES file, a typical one must be assumed.
+ * The D65 standard illuminant has a Luminous efficacy of 177.83, which is used here to convert to Watt/sr.
+ * A more advanced approach would be to add a Blackbody Temperature input to the node and numerically
+ * integrate the Luminous efficacy from the resulting spectral distribution.
+ * Also, the Watt/sr value must be multiplied by 4*pi to get the Watt value that Cycles expects
+ * for lamp strength. Therefore, the conversion here uses 4*pi/177.83 as a Candela to Watt factor.
+ */
+ factor *= 0.0706650768394;
+
+ v_angles.reserve(v_angles_num);
+ for(int i = 0; i < v_angles_num; i++) {
+ v_angles.push_back((float) parser.get_double());
+ }
+
+ h_angles.reserve(h_angles_num);
+ for(int i = 0; i < h_angles_num; i++) {
+ h_angles.push_back((float) parser.get_double());
+ }
+
+ intensity.resize(h_angles_num);
+ for(int i = 0; i < h_angles_num; i++) {
+ intensity[i].reserve(v_angles_num);
+ for(int j = 0; j < v_angles_num; j++) {
+ intensity[i].push_back((float) (factor * parser.get_double()));
+ }
+ }
+
+ return !parser.eof();
+}
+
+bool IESFile::process_type_b()
+{
+ vector<vector<float> > newintensity;
+ newintensity.resize(v_angles.size());
+ for(int i = 0; i < v_angles.size(); i++) {
+ newintensity[i].reserve(h_angles.size());
+ for(int j = 0; j < h_angles.size(); j++) {
+ newintensity[i].push_back(intensity[j][i]);
+ }
+ }
+ intensity.swap(newintensity);
+ h_angles.swap(v_angles);
+
+ float h_first = h_angles[0], h_last = h_angles[h_angles.size()-1];
+ if(h_last != 90.0f) {
+ return false;
+ }
+
+ if(h_first == 0.0f) {
+ /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
+ * full 180° range. */
+ vector<float> new_h_angles;
+ vector<vector<float> > new_intensity;
+ int hnum = h_angles.size();
+ new_h_angles.reserve(2*hnum-1);
+ new_intensity.reserve(2*hnum-1);
+ for(int i = hnum-1; i > 0; i--) {
+ new_h_angles.push_back(90.0f - h_angles[i]);
+ new_intensity.push_back(intensity[i]);
+ }
+ for(int i = 0; i < hnum; i++) {
+ new_h_angles.push_back(90.0f + h_angles[i]);
+ new_intensity.push_back(intensity[i]);
+ }
+ h_angles.swap(new_h_angles);
+ intensity.swap(new_intensity);
+ }
+ else if(h_first == -90.0f) {
+ /* We have full 180° coverage, so just shift to match the angle range convention. */
+ for(int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] += 90.0f;
+ }
+ }
+ /* To get correct results with the cubic interpolation in the kernel, the horizontal range
+ * has to cover all 360°. Therefore, we copy the 0° entry to 360° to ensure full coverage
+ * and seamless interpolation. */
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+
+ float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1];
+ if(v_last != 90.0f) {
+ return false;
+ }
+
+ if(v_first == 0.0f) {
+ /* The range in the file corresponds to 90°-180°, we need to mirror that to get the
+ * full 180° range. */
+ vector<float> new_v_angles;
+ int hnum = h_angles.size();
+ int vnum = v_angles.size();
+ new_v_angles.reserve(2*vnum-1);
+ for(int i = vnum-1; i > 0; i--) {
+ new_v_angles.push_back(90.0f - v_angles[i]);
+ }
+ for(int i = 0; i < vnum; i++) {
+ new_v_angles.push_back(90.0f + v_angles[i]);
+ }
+ for(int i = 0; i < hnum; i++) {
+ vector<float> new_intensity;
+ new_intensity.reserve(2*vnum-1);
+ for(int j = vnum-2; j >= 0; j--) {
+ new_intensity.push_back(intensity[i][j]);
+ }
+ new_intensity.insert(new_intensity.end(), intensity[i].begin(), intensity[i].end());
+ intensity[i].swap(new_intensity);
+ }
+ v_angles.swap(new_v_angles);
+ }
+ else if(v_first == -90.0f) {
+ /* We have full 180° coverage, so just shift to match the angle range convention. */
+ for(int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] += 90.0f;
+ }
+ }
+
+ return true;
+}
+
+bool IESFile::process_type_c()
+{
+ if(h_angles[0] == 90.0f) {
+ /* Some files are stored from 90° to 270°, so we just rotate them to the regular 0°-180° range here. */
+ for(int i = 0; i < v_angles.size(); i++) {
+ h_angles[i] -= 90.0f;
+ }
+ }
+
+ if(h_angles[0] != 0.0f) {
+ return false;
+ }
+
+ if(h_angles.size() == 1) {
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+ }
+
+ if(h_angles[h_angles.size()-1] == 90.0f) {
+ /* Only one quadrant is defined, so we need to mirror twice (from one to two, then to four).
+ * Since the two->four mirroring step might also be required if we get an input of two quadrants,
+ * we only do the first mirror here and later do the second mirror in either case. */
+ int hnum = h_angles.size();
+ for(int i = hnum-2; i >= 0; i--) {
+ h_angles.push_back(180.0f - h_angles[i]);
+ intensity.push_back(intensity[i]);
+ }
+ }
+
+ if(h_angles[h_angles.size()-1] == 180.0f) {
+ /* Mirror half to the full range. */
+ int hnum = h_angles.size();
+ for(int i = hnum-2; i >= 0; i--) {
+ h_angles.push_back(360.0f - h_angles[i]);
+ intensity.push_back(intensity[i]);
+ }
+ }
+
+ /* Some files skip the 360° entry (contrary to standard) because it's supposed to be identical to the 0° entry.
+ * If the file has a discernible order in its spacing, just fix this. */
+ if(h_angles[h_angles.size()-1] != 360.0f) {
+ int hnum = h_angles.size();
+ float last_step = h_angles[hnum-1]-h_angles[hnum-2];
+ float first_step = h_angles[1]-h_angles[0];
+ float difference = 360.0f - h_angles[hnum-1];
+ if(last_step == difference || first_step == difference) {
+ h_angles.push_back(360.0f);
+ intensity.push_back(intensity[0]);
+ }
+ else {
+ return false;
+ }
+ }
+
+ float v_first = v_angles[0], v_last = v_angles[v_angles.size()-1];
+ if(v_first == 90.0f) {
+ if(v_last == 180.0f) {
+ /* Flip to ensure that vertical angles always start at 0°. */
+ for(int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] = 180.0f - v_angles[i];
+ }
+ }
+ else {
+ return false;
+ }
+ }
+ else if(v_first != 0.0f) {
+ return false;
+ }
+
+ return true;
+}
+
+bool IESFile::process()
+{
+ if(h_angles.size() == 0 || v_angles.size() == 0) {
+ return false;
+ }
+
+ if(type == TYPE_B) {
+ if(!process_type_b()) {
+ return false;
+ }
+ }
+ else {
+ assert(type == TYPE_C);
+ if(!process_type_c()) {
+ return false;
+ }
+ }
+
+ assert(v_angles[0] == 0.0f);
+ assert(h_angles[0] == 0.0f);
+ assert(h_angles[h_angles.size()-1] == 360.0f);
+
+ /* Convert from deg to rad. */
+ for(int i = 0; i < v_angles.size(); i++) {
+ v_angles[i] *= M_PI_F / 180.f;
+ }
+ for(int i = 0; i < h_angles.size(); i++) {
+ h_angles[i] *= M_PI_F / 180.f;
+ }
+
+ return true;
+}
+
+IESFile::~IESFile()
+{
+ clear();
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_ies.h b/intern/cycles/util/util_ies.h
new file mode 100644
index 00000000000..5933cb3962a
--- /dev/null
+++ b/intern/cycles/util/util_ies.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011-2018 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_IES_H__
+#define __UTIL_IES_H__
+
+#include "util/util_param.h"
+#include "util/util_vector.h"
+
+CCL_NAMESPACE_BEGIN
+
+class IESFile {
+public:
+ IESFile() {}
+ ~IESFile();
+
+ int packed_size();
+ void pack(float *data);
+
+ bool load(ustring ies);
+ void clear();
+
+protected:
+ bool parse(ustring ies);
+ bool process();
+ bool process_type_b();
+ bool process_type_c();
+
+ /* The brightness distribution is stored in spherical coordinates.
+ * The horizontal angles correspond to to theta in the regular notation
+ * and always span the full range from 0° to 360°.
+ * The vertical angles correspond to phi and always start at 0°. */
+ vector<float> v_angles, h_angles;
+ /* The actual values are stored here, with every entry storing the values
+ * of one horizontal segment. */
+ vector<vector<float> > intensity;
+
+ /* Types of angle representation in IES files. Currently, only B and C are supported. */
+ enum IESType {
+ TYPE_A = 3,
+ TYPE_B = 2,
+ TYPE_C = 1
+ } type;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_IES_H__ */
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index d0e91a2a1c9..fd3199f209f 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -310,6 +310,17 @@ ccl_device_inline float4 float3_to_float4(const float3 a)
return make_float4(a.x, a.y, a.z, 1.0f);
}
+ccl_device_inline float inverse_lerp(float a, float b, float x)
+{
+ return (x - a) / (b - a);
+}
+
+/* Cubic interpolation between b and c, a and d are the previous and next point. */
+ccl_device_inline float cubic_interp(float a, float b, float c, float d, float x)
+{
+ return 0.5f*(((d + 3.0f*(b-c) - a)*x + (2.0f*a - 5.0f*b + 4.0f*c - d))*x + (c - a))*x + b;
+}
+
CCL_NAMESPACE_END
#include "util/util_math_int2.h"
diff --git a/make.bat b/make.bat
index d00a9ecf711..3e2217d010a 100644
--- a/make.bat
+++ b/make.bat
@@ -4,359 +4,66 @@ REM This is for users who like to configure & build Blender with a single comman
setlocal EnableDelayedExpansion
setlocal ENABLEEXTENSIONS
set BLENDER_DIR=%~dp0
-set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
-for %%X in (svn.exe) do (set HAS_SVN=%%~$PATH:X)
-if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
- echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
- goto EOF
-)
-set BUILD_DIR=%BLENDER_DIR%..\build_windows
-set BUILD_TYPE=Release
-rem reset all variables so they do not get accidentally get carried over from previous builds
-set BUILD_DIR_OVERRRIDE=
-set BUILD_CMAKE_ARGS=
-set BUILD_ARCH=
-set BUILD_VS_VER=
-set BUILD_VS_YEAR=
-set BUILD_VS_LIBDIRPOST=
-set BUILD_VS_LIBDIR=
-set BUILD_VS_SVNDIR=
-set BUILD_NGE=
-set KEY_NAME=
-set MSBUILD_PLATFORM=
-set MUST_CLEAN=
-set NOBUILD=
-set TARGET=
-set WINDOWS_ARCH=
-set TESTS_CMAKE_ARGS=
-:argv_loop
-if NOT "%1" == "" (
- REM Help Message
- if "%1" == "help" (
- goto HELP
- )
+call "%BLENDER_DIR%\build_files\windows\reset_variables.cmd"
- REM Build Types
- if "%1" == "debug" (
- set BUILD_TYPE=Debug
- REM Build Configurations
- ) else if "%1" == "noge" (
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_GAMEENGINE=OFF -DWITH_PLAYER=OFF
- set BUILD_NGE=_noge
- ) else if "%1" == "builddir" (
- set BUILD_DIR_OVERRRIDE="%BLENDER_DIR%..\%2"
- shift /1
- ) else if "%1" == "with_tests" (
- set TESTS_CMAKE_ARGS=-DWITH_GTESTS=On
- ) else if "%1" == "full" (
- set TARGET=Full
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\blender_full.cmake"
- ) else if "%1" == "lite" (
- set TARGET=Lite
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\blender_lite.cmake"
- ) else if "%1" == "cycles" (
- set TARGET=Cycles
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\cycles_standalone.cmake"
- ) else if "%1" == "headless" (
- set TARGET=Headless
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\blender_headless.cmake"
- ) else if "%1" == "bpy" (
- set TARGET=Bpy
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\bpy_module.cmake"
- ) else if "%1" == "release" (
- set TARGET=Release
- ) else if "%1" == "x86" (
- set BUILD_ARCH=x86
- ) else if "%1" == "x64" (
- set BUILD_ARCH=x64
- ) else if "%1" == "2017" (
- set BUILD_VS_VER=15
- set BUILD_VS_YEAR=2017
- set BUILD_VS_LIBDIRPOST=vc14
- ) else if "%1" == "2015" (
- set BUILD_VS_VER=14
- set BUILD_VS_YEAR=2015
- set BUILD_VS_LIBDIRPOST=vc14
- ) else if "%1" == "2013" (
- set BUILD_VS_VER=12
- set BUILD_VS_YEAR=2013
- set BUILD_VS_LIBDIRPOST=vc12
- ) else if "%1" == "packagename" (
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DCPACK_OVERRIDE_PACKAGENAME="%2"
- shift /1
- ) else if "%1" == "nobuild" (
- set NOBUILD=1
- ) else if "%1" == "showhash" (
- for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i
- cd release/datafiles/locale
- for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i
- cd %~dp0
- cd release/scripts/addons
- for /f "delims=" %%i in ('git rev-parse HEAD') do echo Addons_Hash=%%i
- cd %~dp0
- goto EOF
- REM Non-Build Commands
- ) else if "%1" == "update" (
- svn up ../lib/*
- git pull --rebase
- git submodule update --remote
- goto EOF
- ) else if "%1" == "clean" (
- set MUST_CLEAN=1
- ) else (
- echo Command "%1" unknown, aborting!
- goto EOF
- )
+call "%BLENDER_DIR%\build_files\windows\check_spaces_in_path.cmd"
+if errorlevel 1 goto EOF
- shift /1
- goto argv_loop
-)
-if "%BUILD_ARCH%"=="" (
- if "%PROCESSOR_ARCHITECTURE%" == "AMD64" (
- set WINDOWS_ARCH= Win64
- set BUILD_ARCH=x64
- ) else if "%PROCESSOR_ARCHITEW6432%" == "AMD64" (
- set WINDOWS_ARCH= Win64
- set BUILD_ARCH=x64
- ) else (
- set WINDOWS_ARCH=
- set BUILD_ARCH=x86
- )
-) else if "%BUILD_ARCH%"=="x64" (
- set WINDOWS_ARCH= Win64
-) else if "%BUILD_ARCH%"=="x86" (
- set WINDOWS_ARCH=
-)
+call "%BLENDER_DIR%\build_files\windows\parse_arguments.cmd" %*
+if errorlevel 1 goto EOF
-if "%BUILD_VS_VER%"=="" (
- set BUILD_VS_VER=12
- set BUILD_VS_YEAR=2013
- set BUILD_VS_LIBDIRPOST=vc12
-)
+call "%BLENDER_DIR%\build_files\windows\find_dependencies.cmd"
+if errorlevel 1 goto EOF
-if "%BUILD_ARCH%"=="x64" (
- set MSBUILD_PLATFORM=x64
-) else if "%BUILD_ARCH%"=="x86" (
- set MSBUILD_PLATFORM=win32
+if "%SHOW_HELP%" == "1" (
+ call "%BLENDER_DIR%\build_files\windows\show_help.cmd"
+ goto EOF
)
-
-if "%target%"=="Release" (
- rem for vc12 check for both cuda 7.5 and 8
- if "%CUDA_PATH%"=="" (
- echo Cuda Not found, aborting!
- goto EOF
- )
- set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
+if "%BUILD_UPDATE%" == "1" (
+ call "%BLENDER_DIR%\build_files\windows\update_sources.cmd"
+ goto EOF
)
-:DetectMSVC
-REM Detect MSVC Installation for 2013-2015
-if DEFINED VisualStudioVersion goto msvc_detect_finally
-set VALUE_NAME=ProductDir
-REM Check 64 bits
-set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
-for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
-if DEFINED MSVC_VC_DIR goto msvc_detect_finally
-REM Check 32 bits
-set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\%BUILD_VS_VER%.0\Setup\VC"
-for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set MSVC_VC_DIR=%%C
-if DEFINED MSVC_VC_DIR goto msvc_detect_finally
-:msvc_detect_finally
-if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
-if DEFINED MSVC_VC_DIR goto sanity_checks
-
-rem MSVC Build environment 2017 and up.
-for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SXS\VS7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
-if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
-REM Check 32 bits
-for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\sxs\vs7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
-if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
-:msvc_detect_finally_2017
-if DEFINED MSVC_VS_DIR call "%MSVC_VS_DIR%\Common7\Tools\VsDevCmd.bat"
+call "%BLENDER_DIR%\build_files\windows\detect_architecture.cmd"
-:sanity_checks
-REM Sanity Checks
-where /Q msbuild
-if %ERRORLEVEL% NEQ 0 (
- if "%BUILD_VS_VER%"=="12" (
- rem vs12 not found, try vs14
- echo Visual Studio 2013 not found, trying Visual Studio 2015.
- set BUILD_VS_VER=14
- set BUILD_VS_YEAR=2015
- set BUILD_VS_LIBDIRPOST=vc14
- goto DetectMSVC
- ) else (
- echo Error: "MSBuild" command not in the PATH.
- echo You must have MSVC installed and run this from the "Developer Command Prompt"
- echo ^(available from Visual Studio's Start menu entry^), aborting!
+if "%BUILD_VS_YEAR%" == "" (
+ call "%BLENDER_DIR%\build_files\windows\autodetect_msvc.cmd"
+ if errorlevel 1 (
+ echo Visual Studio not found ^(try with the 'verbose' switch for more information^)
goto EOF
)
-)
-
-
-set BUILD_DIR=%BUILD_DIR%_%TARGET%%BUILD_NGE%_%BUILD_ARCH%_vc%BUILD_VS_VER%_%BUILD_TYPE%
-if NOT "%BUILD_DIR_OVERRRIDE%"=="" (
- set BUILD_DIR=%BUILD_DIR_OVERRRIDE%
-)
-
-where /Q cmake
-if %ERRORLEVEL% NEQ 0 (
- echo Error: "CMake" command not in the PATH.
- echo You must have CMake installed and added to your PATH, aborting!
- goto EOF
-)
-
-if "%BUILD_ARCH%"=="x64" (
- set BUILD_VS_SVNDIR=win64_%BUILD_VS_LIBDIRPOST%
-) else if "%BUILD_ARCH%"=="x86" (
- set BUILD_VS_SVNDIR=windows_%BUILD_VS_LIBDIRPOST%
-)
-set BUILD_VS_LIBDIR="%BLENDER_DIR%..\lib\%BUILD_VS_SVNDIR%"
-
-if NOT EXIST %BUILD_VS_LIBDIR% (
- rem libs not found, but svn is on the system
- if not "%HAS_SVN%"=="" (
- echo.
- echo The required external libraries in %BUILD_VS_LIBDIR% are missing
- echo.
- set /p GetLibs= "Would you like to download them? (y/n)"
- if /I "!GetLibs!"=="Y" (
- echo.
- echo Downloading %BUILD_VS_SVNDIR% libraries, please wait.
- echo.
- svn checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/%BUILD_VS_SVNDIR% %BUILD_VS_LIBDIR%
- )
+) else (
+ call "%BLENDER_DIR%\build_files\windows\detect_msvc%BUILD_VS_YEAR%.cmd"
+ if errorlevel 1 (
+ echo Visual Studio %BUILD_VS_YEAR% not found ^(try with the 'verbose' switch for more information^)
+ goto EOF
)
)
-if NOT EXIST %BUILD_VS_LIBDIR% (
- echo Error: Path to libraries not found "%BUILD_VS_LIBDIR%"
- echo This is needed for building, aborting!
- goto EOF
-)
+call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd"
-if "%TARGET%"=="" (
- echo Error: Convenience target not set
- echo This is required for building, aborting!
- echo .
- goto HELP
-)
+echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR%
-set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -G "Visual Studio %BUILD_VS_VER% %BUILD_VS_YEAR%%WINDOWS_ARCH%" %TESTS_CMAKE_ARGS%
-if NOT EXIST %BUILD_DIR%\nul (
- mkdir %BUILD_DIR%
-)
-if "%MUST_CLEAN%"=="1" (
- echo Cleaning %BUILD_DIR%
- msbuild ^
- %BUILD_DIR%\Blender.sln ^
- /target:clean ^
- /property:Configuration=%BUILD_TYPE% ^
- /verbosity:minimal ^
- /p:platform=%MSBUILD_PLATFORM%
+call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd"
+if errorlevel 1 goto EOF
- if %ERRORLEVEL% NEQ 0 (
- echo Cleaned "%BUILD_DIR%"
- )
- goto EOF
-)
-REM Only configure on first run or when called with nobuild
-if NOT EXIST %BUILD_DIR%\Blender.sln set MUST_CONFIGURE=1
-if "%NOBUILD%"=="1" set MUST_CONFIGURE=1
-
-if "%MUST_CONFIGURE%"=="1" (
- cmake ^
- %BUILD_CMAKE_ARGS% ^
- -H%BLENDER_DIR% ^
- -B%BUILD_DIR% ^
- %BUILD_CMAKE_ARGS%
-
- if %ERRORLEVEL% NEQ 0 (
- echo "Configuration Failed"
- goto EOF
- )
-)
-if DEFINED MSVC_VC_DIR echo call "%MSVC_VC_DIR%\vcvarsall.bat" > %BUILD_DIR%\rebuild.cmd
-if DEFINED MSVC_VS_DIR echo call "%MSVC_VS_DIR%\Common7\Tools\VsDevCmd.bat" > %BUILD_DIR%\rebuild.cmd
-echo cmake . >> %BUILD_DIR%\rebuild.cmd
-echo msbuild ^
- %BUILD_DIR%\Blender.sln ^
- /target:build ^
- /property:Configuration=%BUILD_TYPE% ^
- /maxcpucount:2 ^
- /verbosity:minimal ^
- /p:platform=%MSBUILD_PLATFORM% ^
- /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log >> %BUILD_DIR%\rebuild.cmd
-echo msbuild ^
- %BUILD_DIR%\INSTALL.vcxproj ^
- /property:Configuration=%BUILD_TYPE% ^
- /verbosity:minimal ^
- /p:platform=%MSBUILD_PLATFORM% >> %BUILD_DIR%\rebuild.cmd
+call "%BLENDER_DIR%\build_files\windows\check_submodules.cmd"
+if errorlevel 1 goto EOF
-if "%NOBUILD%"=="1" goto EOF
+if "%BUILD_WITH_NINJA%" == "" (
+ call "%BLENDER_DIR%\build_files\windows\configure_msbuild.cmd"
+ if errorlevel 1 goto EOF
-msbuild ^
- %BUILD_DIR%\Blender.sln ^
- /target:build ^
- /property:Configuration=%BUILD_TYPE% ^
- /maxcpucount:2 ^
- /verbosity:minimal ^
- /p:platform=%MSBUILD_PLATFORM% ^
- /flp:Summary;Verbosity=minimal;LogFile=%BUILD_DIR%\Build.log
+ call "%BLENDER_DIR%\build_files\windows\build_msbuild.cmd"
+ if errorlevel 1 goto EOF
+) else (
+ call "%BLENDER_DIR%\build_files\windows\configure_ninja.cmd"
+ if errorlevel 1 goto EOF
-if %ERRORLEVEL% NEQ 0 (
- echo "Build Failed"
- goto EOF
+ call "%BLENDER_DIR%\build_files\windows\build_ninja.cmd"
+ if errorlevel 1 goto EOF
)
-msbuild ^
- %BUILD_DIR%\INSTALL.vcxproj ^
- /property:Configuration=%BUILD_TYPE% ^
- /verbosity:minimal ^
- /p:platform=%MSBUILD_PLATFORM%
-
-echo.
-echo At any point you can optionally modify your build configuration by editing:
-echo "%BUILD_DIR%\CMakeCache.txt", then run "rebuild.cmd" in the build folder to build with the changes applied.
-echo.
-echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender.exe"
-echo.
-goto EOF
-:HELP
- echo.
- echo Convenience targets
- echo - release ^(identical to the official blender.org builds^)
- echo - full ^(same as release minus the cuda kernels^)
- echo - lite
- echo - headless
- echo - cycles
- echo - bpy
- echo.
- echo Utilities ^(not associated with building^)
- echo - clean ^(Target must be set^)
- echo - update
- echo - nobuild ^(only generate project files^)
- echo - showhash ^(Show git hashes of source tree^)
- echo.
- echo Configuration options
- echo - with_tests ^(enable building unit tests^)
- echo - noge ^(disable building game enginge and player^)
- echo - debug ^(Build an unoptimized debuggable build^)
- echo - packagename [newname] ^(override default cpack package name^)
- echo - buildir [newdir] ^(override default build folder^)
- echo - x86 ^(override host auto-detect and build 32 bit code^)
- echo - x64 ^(override host auto-detect and build 64 bit code^)
- echo - 2013 ^(build with visual studio 2013^)
- echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
- echo - 2017 ^(build with visual studio 2017^) [EXPERIMENTAL]
- echo.
-
:EOF
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 28e39959c7e..466e7dfa325 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -328,7 +328,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "delimit")
layout_info = layout
- layout_info.label(text=iface_("Faces: %d") % md.face_count, translate=False)
+ layout_info.label(text=iface_("Face Count: {:,}".format(md.face_count)),
+ translate=False)
def DISPLACE(self, layout, ob, md):
has_texture = (md.texture is not None)
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 591180f08b4..d60710db4aa 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -229,6 +229,7 @@ shader_node_categories = [
NodeItem("ShaderNodeTexChecker"),
NodeItem("ShaderNodeTexBrick"),
NodeItem("ShaderNodeTexPointDensity"),
+ NodeItem("ShaderNodeTexIES"),
]),
ShaderNodeCategory("SH_NEW_OP_COLOR", "Color", items=[
NodeItem("ShaderNodeMixRGB"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index f3cbcd7b99f..c654dd51e2a 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -796,6 +796,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, c
#define SH_NODE_UVALONGSTROKE 191
#define SH_NODE_TEX_POINTDENSITY 192
#define SH_NODE_BSDF_PRINCIPLED 193
+#define SH_NODE_TEX_IES 194
#define SH_NODE_EEVEE_SPECULAR 195
#define SH_NODE_BEVEL 197
#define SH_NODE_DISPLACEMENT 198
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 259c5189896..dbaf3f2ee9e 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -560,6 +560,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
}
+ else if (node->type == SH_NODE_TEX_IES) {
+ NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
+ rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
+ }
}
}
break;
@@ -576,6 +580,10 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
}
+ else if (node->type == SH_NODE_TEX_IES) {
+ NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
+ rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
+ }
}
}
break;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index d86b73ab1a9..a25b21a995a 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3545,6 +3545,7 @@ static void registerShaderNodes(void)
register_node_type_sh_tex_checker();
register_node_type_sh_tex_brick();
register_node_type_sh_tex_pointdensity();
+ register_node_type_sh_tex_ies();
}
static void registerTextureNodes(void)
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 7fd7b791a3f..a99057ac0ad 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -50,6 +50,7 @@
#include "BLI_blenlib.h"
#include "BLI_threads.h"
#include "BLI_math.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BLT_translation.h"
@@ -4071,9 +4072,11 @@ void BKE_ptcache_update_info(PTCacheID *pid)
}
else {
PTCacheMem *pm = cache->mem_cache.first;
- float bytes = 0.0f;
- int i, mb;
-
+ char formatted_tot[16];
+ char formatted_mem[15];
+ long long int bytes = 0.0f;
+ int i;
+
for (; pm; pm=pm->next) {
for (i=0; i<BPHYS_TOT_DATA; i++)
bytes += MEM_allocN_len(pm->data[i]);
@@ -4088,12 +4091,10 @@ void BKE_ptcache_update_info(PTCacheID *pid)
totframes++;
}
- mb = (bytes > 1024.0f * 1024.0f);
+ BLI_str_format_int_grouped(formatted_tot, totframes);
+ BLI_str_format_byte_unit(formatted_mem, bytes, true);
- BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"),
- totframes,
- bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
- mb ? IFACE_("Mb") : IFACE_("kb"));
+ BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%s frames in memory (%s)"), formatted_tot, formatted_mem);
}
if (cache->flag & PTCACHE_OUTDATED) {
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 48be9d1842f..faa8dc03615 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -71,6 +71,7 @@ char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT A
size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL();
size_t BLI_str_format_int_grouped(char dst[16], int num) ATTR_NONNULL();
+void BLI_str_format_byte_unit(char dst[15], long long int size, const bool base_10) ATTR_NONNULL();
int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 1a6fd082e95..49630347032 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -799,6 +799,7 @@ int BLI_str_rstrip_float_zero(char *str, const char pad)
while (end_p != p && *end_p == '0') {
*end_p = pad;
end_p--;
+ totstrip++;
}
}
}
@@ -995,6 +996,41 @@ size_t BLI_str_format_int_grouped(char dst[16], int num)
}
/**
+ * Format a size in bytes using binary units.
+ * 1000 -> 1 KB
+ * Number of decimal places grows with the used unit (e.g. 1.5 MB, 1.55 GB, 1.545 TB).
+ *
+ * \param dst The resulting string. Dimension of 14 to support largest possible value for \a bytes (LLONG_MAX).
+ * \param bytes Number to format
+ * \param base_10 Calculate using base 10 (GB, MB, ...) or 2 (GiB, MiB, ...)
+ */
+void BLI_str_format_byte_unit(char dst[15], long long int bytes, const bool base_10)
+{
+ double bytes_converted = bytes;
+ int order = 0;
+ int decimals;
+ const int base = base_10 ? 1000 : 1024;
+ const char *units_base_10[] = {"B", "KB", "MB", "GB", "TB", "PB"};
+ const char *units_base_2[] = {"B", "KiB", "MiB", "GiB", "TiB", "PiB"};
+ const int tot_units = ARRAY_SIZE(units_base_2);
+
+ BLI_STATIC_ASSERT(ARRAY_SIZE(units_base_2) == ARRAY_SIZE(units_base_10), "array size mismatch");
+
+ while ((ABS(bytes_converted) >= base) && ((order + 1) < tot_units)) {
+ bytes_converted /= base;
+ order++;
+ }
+ decimals = MAX2(order - 1, 0);
+
+ /* Format value first, stripping away floating zeroes. */
+ const size_t dst_len = 15;
+ size_t len = BLI_snprintf_rlen(dst, dst_len, "%.*f", decimals, bytes_converted);
+ len -= (size_t)BLI_str_rstrip_float_zero(dst, '\0');
+ dst[len++] = ' ';
+ BLI_strncpy(dst + len, base_10 ? units_base_10[order] : units_base_2[order], dst_len - len);
+}
+
+/**
* Find the ranges needed to split \a str into its individual words.
*
* \param str: The string to search for words.
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index 761f3982e28..e6f5d9839ea 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -488,7 +488,8 @@ void BLI_spin_lock(SpinLock *spin)
#elif defined(_MSC_VER)
while (InterlockedExchangeAcquire(spin, 1)) {
while (*spin) {
- /* pass */
+ /* Spinlock hint for processors with hyperthreading. */
+ YieldProcessor();
}
}
#else
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index dfcf5fd5d8d..d2bfcfa76df 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -410,6 +410,7 @@ static void stats_string(ViewLayer *view_layer)
uintptr_t mem_in_use, mmap_in_use;
char memstr[MAX_INFO_MEM_LEN];
char gpumemstr[MAX_INFO_MEM_LEN] = "";
+ char formatted_mem[15];
char *s;
size_t ofs = 0;
@@ -445,20 +446,25 @@ static void stats_string(ViewLayer *view_layer)
/* get memory statistics */
- ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem:%.2fM"),
- (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0);
- if (mmap_in_use)
- BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0);
+ BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, true);
+ ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, IFACE_(" | Mem: %s"), formatted_mem);
+
+ if (mmap_in_use) {
+ BLI_str_format_byte_unit(formatted_mem, mmap_in_use, true);
+ BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%s)"), formatted_mem);
+ }
if (GPU_mem_stats_supported()) {
int gpu_free_mem, gpu_tot_memory;
GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem);
- ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem:%.2fM"), (double)((gpu_free_mem)) / 1024.0);
+ BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, true);
+ ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, IFACE_(" | Free GPU Mem: %s"), formatted_mem);
if (gpu_tot_memory) {
- BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%.2fM"), (double)((gpu_tot_memory)) / 1024.0);
+ BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, true);
+ BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_("/%s"), formatted_mem);
}
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index ca6ae5955a9..19e2ae9808a 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -1021,6 +1021,21 @@ static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), Pointer
uiItemR(layout, ptr, "component", 0, "", ICON_NONE);
}
+static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayout *row;
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
+
+ row = uiLayoutRow(layout, true);
+
+ if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL)
+ uiItemR(row, ptr, "ies", 0, "", ICON_NONE);
+ else
+ uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
+}
+
static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiLayout *row;
@@ -1189,6 +1204,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_OUTPUT_LINESTYLE:
ntype->draw_buttons = node_buts_output_linestyle;
break;
+ case SH_NODE_TEX_IES:
+ ntype->draw_buttons = node_shader_buts_ies;
+ break;
case SH_NODE_BEVEL:
ntype->draw_buttons = node_shader_buts_bevel;
break;
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 66eaf34865f..cd8a49fd697 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -1110,7 +1110,7 @@ static void view3d_ndof_pan_zoom(
static void view3d_ndof_orbit(
const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
/* optional, can be NULL*/
- ViewOpsData *vod)
+ ViewOpsData *vod, const bool apply_dyn_ofs)
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
@@ -1173,7 +1173,7 @@ static void view3d_ndof_orbit(
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
}
- if (vod) {
+ if (apply_dyn_ofs) {
viewrotate_apply_dyn_ofs(vod, rv3d->viewquat);
}
}
@@ -1342,7 +1342,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
}
}
@@ -1424,7 +1424,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true);
}
}
else { /* free/explore (like fly mode) */
@@ -1442,7 +1442,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
ED_view3d_distance_set(rv3d, 0.0f);
if (has_rotation) {
- view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL);
+ view3d_ndof_orbit(ndof, vod->sa, vod->ar, NULL, false);
}
ED_view3d_distance_set(rv3d, dist_backup);
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 613830bac8d..af1045ee059 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -891,6 +891,12 @@ typedef struct NodeShaderUVMap {
char uv_map[64];
} NodeShaderUVMap;
+typedef struct NodeShaderTexIES {
+ int mode;
+
+ char filepath[1024]; /* 1024 = FILE_MAX */
+} NodeShaderTexIES;
+
typedef struct NodeSunBeams {
float source[2];
@@ -904,6 +910,9 @@ typedef struct NodeSunBeams {
/* script node flag */
#define NODE_SCRIPT_AUTO_UPDATE 1
+/* ies node mode */
+#define NODE_IES_INTERNAL 0
+#define NODE_IES_EXTERNAL 1
/* frame node flags */
#define NODE_FRAME_SHRINK 1 /* keep the bounding box minimal */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 4744b2e33df..1cd907aeb91 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -527,6 +527,7 @@ extern StructRNA RNA_ShaderNodeCombineRGB;
extern StructRNA RNA_ShaderNodeExtendedMaterial;
extern StructRNA RNA_ShaderNodeGeometry;
extern StructRNA RNA_ShaderNodeHueSaturation;
+extern StructRNA RNA_ShaderNodeIESLight;
extern StructRNA RNA_ShaderNodeInvert;
extern StructRNA RNA_ShaderNodeLampData;
extern StructRNA RNA_ShaderNodeMapping;
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e05e9d32277..182e606a357 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -2950,6 +2950,30 @@ static bNodeSocket *rna_NodeOutputFile_slots_new(ID *id, bNode *node, bContext *
return sock;
}
+static void rna_ShaderNodeTexIES_mode_set(PointerRNA *ptr, int value)
+{
+ bNode *node = (bNode *)ptr->data;
+ NodeShaderTexIES *nss = node->storage;
+
+ if (nss->mode != value) {
+ nss->mode = value;
+ nss->filepath[0] = '\0';
+
+ /* replace text datablock by filepath */
+ if (node->id) {
+ Text *text = (Text *)node->id;
+
+ if (value == NODE_IES_EXTERNAL && text->name) {
+ BLI_strncpy(nss->filepath, text->name, sizeof(nss->filepath));
+ BLI_path_rel(nss->filepath, G.main->name);
+ }
+
+ id_us_min(node->id);
+ node->id = NULL;
+ }
+ }
+}
+
static void rna_ShaderNodeScript_mode_set(PointerRNA *ptr, int value)
{
bNode *node = (bNode *)ptr->data;
@@ -3292,6 +3316,12 @@ static const EnumPropertyItem node_script_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static EnumPropertyItem node_ies_mode_items[] = {
+ {NODE_IES_INTERNAL, "INTERNAL", 0, "Internal", "Use internal text datablock"},
+ {NODE_IES_EXTERNAL, "EXTERNAL", 0, "External", "Use external .ies file"},
+ {0, NULL, 0, NULL, NULL}
+};
+
static const EnumPropertyItem node_principled_distribution_items[] = {
{SHD_GLOSSY_GGX, "GGX", 0, "GGX", ""},
{SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", ""},
@@ -4403,6 +4433,32 @@ static void def_sh_subsurface(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeSubsurface_update");
}
+static void def_sh_tex_ies(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "ies", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_struct_type(prop, "Text");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_ui_text(prop, "IES Text", "Internal IES file");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "NodeShaderTexIES", "storage");
+
+ prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_ui_text(prop, "File Path", "IES light path");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeTexIES_mode_set", NULL);
+ RNA_def_property_enum_items(prop, node_ies_mode_items);
+ RNA_def_property_ui_text(prop, "Source", "Whether the IES file is loaded from disk or from a Text datablock");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "bNode", NULL);
+}
+
static void def_sh_script(StructRNA *srna)
{
PropertyRNA *prop;
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 5acd0a9fcea..67c86180188 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -173,6 +173,7 @@ set(SRC
shader/nodes/node_shader_fresnel.c
shader/nodes/node_shader_geometry.c
shader/nodes/node_shader_holdout.c
+ shader/nodes/node_shader_ies_light.c
shader/nodes/node_shader_layer_weight.c
shader/nodes/node_shader_light_falloff.c
shader/nodes/node_shader_light_path.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 3d6a8647628..158d20a5c19 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -136,6 +136,7 @@ void register_node_type_sh_tex_musgrave(void);
void register_node_type_sh_tex_noise(void);
void register_node_type_sh_tex_checker(void);
void register_node_type_sh_bump(void);
+void register_node_type_sh_tex_ies(void);
#endif
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index efb8eb66737..437093a9cb3 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -126,6 +126,7 @@ DefNode( ShaderNode, SH_NODE_COMBXYZ, 0, "CO
DefNode( ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEVEL", Bevel, "Bevel", "" )
DefNode( ShaderNode, SH_NODE_DISPLACEMENT, def_sh_displacement, "DISPLACEMENT", Displacement, "Displacement", "" )
DefNode( ShaderNode, SH_NODE_VECTOR_DISPLACEMENT,def_sh_vector_displacement,"VECTOR_DISPLACEMENT",VectorDisplacement,"Vector Displacement","" )
+DefNode( ShaderNode, SH_NODE_TEX_IES, def_sh_tex_ies, "TEX_IES", TexIES, "IES Texture", "" )
DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
diff --git a/source/blender/nodes/shader/nodes/node_shader_ies_light.c b/source/blender/nodes/shader/nodes/node_shader_ies_light.c
new file mode 100644
index 00000000000..8084f445e34
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_ies_light.c
@@ -0,0 +1,61 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2018 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** IES Light ******************** */
+
+static bNodeSocketTemplate sh_node_tex_ies_in[] = {
+ { SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f, PROP_NONE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_tex_ies_out[] = {
+ { SOCK_FLOAT, 0, N_("Fac")},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_tex_ies(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ NodeShaderTexIES *tex = MEM_callocN(sizeof(NodeShaderTexIES), "NodeShaderIESLight");
+ node->storage = tex;
+}
+
+/* node type definition */
+void register_node_type_sh_tex_ies(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_TEX_IES, "IES Texture", NODE_CLASS_TEXTURE, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_tex_ies_in, sh_node_tex_ies_out);
+ node_type_init(&ntype, node_shader_init_tex_ies);
+ node_type_storage(&ntype, "NodeShaderTexIES", node_free_standard_storage, node_copy_standard_storage);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc
index f6f7e17c8ca..f3a12cef26a 100644
--- a/tests/gtests/blenlib/BLI_string_test.cc
+++ b/tests/gtests/blenlib/BLI_string_test.cc
@@ -364,6 +364,72 @@ TEST(string, StrFormatIntGrouped)
EXPECT_STREQ("-999", num_str);
}
+/* BLI_str_format_byte_unit */
+TEST(string, StrFormatByteUnits)
+{
+ char size_str[15];
+ long long int size;
+
+ /* Base 10 */
+ BLI_str_format_byte_unit(size_str, size = 0, true);
+ EXPECT_STREQ("0 B", size_str);
+ BLI_str_format_byte_unit(size_str, size = -0, true);
+ EXPECT_STREQ("0 B", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 1, true);
+ EXPECT_STREQ("1 B", size_str);
+ BLI_str_format_byte_unit(size_str, size = -1, true);
+ EXPECT_STREQ("-1 B", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 1000, true);
+ EXPECT_STREQ("1 KB", size_str);
+ BLI_str_format_byte_unit(size_str, size = -1000, true);
+ EXPECT_STREQ("-1 KB", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 1024, true);
+ EXPECT_STREQ("1 KB", size_str);
+ BLI_str_format_byte_unit(size_str, size = -1024, true);
+ EXPECT_STREQ("-1 KB", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 9223372036854775807, true); /* LLONG_MAX - largest possible value */
+ EXPECT_STREQ("9223.372 PB", size_str);
+ BLI_str_format_byte_unit(size_str, size = -9223372036854775807, true);
+ EXPECT_STREQ("-9223.372 PB", size_str);
+
+
+ /* Base 2 */
+ BLI_str_format_byte_unit(size_str, size = 0, false);
+ EXPECT_STREQ("0 B", size_str);
+ BLI_str_format_byte_unit(size_str, size = -0, false);
+ EXPECT_STREQ("0 B", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 1, false);
+ EXPECT_STREQ("1 B", size_str);
+ BLI_str_format_byte_unit(size_str, size = -1, false);
+ EXPECT_STREQ("-1 B", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 1000, false);
+ EXPECT_STREQ("1000 B", size_str);
+ BLI_str_format_byte_unit(size_str, size = -1000, false);
+ EXPECT_STREQ("-1000 B", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 1024, false);
+ EXPECT_STREQ("1 KiB", size_str);
+ BLI_str_format_byte_unit(size_str, size = -1024, false);
+ EXPECT_STREQ("-1 KiB", size_str);
+
+ BLI_str_format_byte_unit(size_str, size = 9223372036854775807, false); /* LLONG_MAX - largest possible value */
+ EXPECT_STREQ("8192.0 PiB", size_str);
+ BLI_str_format_byte_unit(size_str, size = -9223372036854775807, false);
+ EXPECT_STREQ("-8192.0 PiB", size_str);
+
+ /* Test maximum string length. */
+ BLI_str_format_byte_unit(size_str, size = -9223200000000000000, false);
+ EXPECT_STREQ("-8191.8472 PiB", size_str);
+}
+
+
+
#define STRING_FIND_SPLIT_WORDS_EX(word_str_src, word_str_src_len, limit_words, ...) \
{ \
int word_info[][2] = \