Merged changes in the trunk up to revision 50607.
Conflicts resolved: source/blender/blenloader/intern/readfile.c
This commit is contained in:
@@ -132,7 +132,7 @@ option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
|
||||
option(WITH_GAMEENGINE "Enable Game Engine" ON)
|
||||
option(WITH_PLAYER "Build Player" OFF)
|
||||
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)
|
||||
option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" ON)
|
||||
option(WITH_COMPOSITOR_LEGACY "Enable legacy compositor" OFF)
|
||||
|
||||
# GHOST Windowing Library Options
|
||||
option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF)
|
||||
@@ -672,6 +672,31 @@ if(UNIX AND NOT APPLE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
|
||||
|
||||
message(STATUS "CYCLES_OSL = ${CYCLES_OSL}")
|
||||
|
||||
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
|
||||
find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
|
||||
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
|
||||
# WARNING! depends on correct order of OSL libs linking
|
||||
list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
|
||||
find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
|
||||
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
|
||||
|
||||
if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
|
||||
set(OSL_FOUND TRUE)
|
||||
message(STATUS "OSL includes = ${OSL_INCLUDES}")
|
||||
message(STATUS "OSL library = ${OSL_LIBRARIES}")
|
||||
message(STATUS "OSL compiler = ${OSL_COMPILER}")
|
||||
else()
|
||||
message(STATUS "OSL not found")
|
||||
endif()
|
||||
|
||||
include_directories(${OSL_INCLUDES})
|
||||
endif()
|
||||
|
||||
# OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed
|
||||
set(PLATFORM_LINKLIBS "-lutil -lc -lm -lpthread -lstdc++")
|
||||
|
||||
@@ -816,6 +841,31 @@ elseif(WIN32)
|
||||
add_definitions(-D__SSE__ -D__MMX__)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
|
||||
|
||||
message(STATUS "CYCLES_OSL = ${CYCLES_OSL}")
|
||||
|
||||
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
|
||||
find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
|
||||
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
|
||||
# WARNING! depends on correct order of OSL libs linking
|
||||
list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
|
||||
find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
|
||||
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
|
||||
|
||||
if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
|
||||
set(OSL_FOUND TRUE)
|
||||
message(STATUS "OSL includes = ${OSL_INCLUDES}")
|
||||
message(STATUS "OSL library = ${OSL_LIBRARIES}")
|
||||
message(STATUS "OSL compiler = ${OSL_COMPILER}")
|
||||
else()
|
||||
message(STATUS "OSL not found")
|
||||
endif()
|
||||
|
||||
include_directories(${OSL_INCLUDES})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(PLATFORM_LINKLIBS ws2_32 vfw32 winmm kernel32 user32 gdi32 comdlg32 advapi32 shfolder shell32 ole32 oleaut32 uuid)
|
||||
|
||||
@@ -1432,6 +1482,31 @@ elseif(APPLE)
|
||||
set(OPENIMAGEIO_DEFINITIONS "-DOIIO_STATIC_BUILD")
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(CYCLES_OSL ${LIBDIR}/osl CACHE PATH "Path to OpenShadingLanguage installation")
|
||||
|
||||
message(STATUS "CYCLES_OSL = ${CYCLES_OSL}")
|
||||
|
||||
find_library(OSL_LIB_EXEC NAMES oslexec PATHS ${CYCLES_OSL}/lib)
|
||||
find_library(OSL_LIB_COMP NAMES oslcomp PATHS ${CYCLES_OSL}/lib)
|
||||
find_library(OSL_LIB_QUERY NAMES oslquery PATHS ${CYCLES_OSL}/lib)
|
||||
# WARNING! depends on correct order of OSL libs linking
|
||||
list(APPEND OSL_LIBRARIES ${OSL_LIB_COMP} ${OSL_LIB_EXEC} ${OSL_LIB_QUERY})
|
||||
find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include)
|
||||
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin)
|
||||
|
||||
if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
|
||||
set(OSL_FOUND TRUE)
|
||||
message(STATUS "OSL includes = ${OSL_INCLUDES}")
|
||||
message(STATUS "OSL library = ${OSL_LIBRARIES}")
|
||||
message(STATUS "OSL compiler = ${OSL_COMPILER}")
|
||||
else()
|
||||
message(STATUS "OSL not found")
|
||||
endif()
|
||||
|
||||
include_directories(${OSL_INCLUDES})
|
||||
endif()
|
||||
|
||||
set(EXETYPE MACOSX_BUNDLE)
|
||||
|
||||
set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g")
|
||||
|
@@ -251,6 +251,10 @@ check_sparse:
|
||||
$(CMAKE_CONFIG)
|
||||
cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_sparse.py
|
||||
|
||||
check_smatch:
|
||||
$(CMAKE_CONFIG)
|
||||
cd $(BUILD_DIR) ; python3.2 $(BLENDER_DIR)/build_files/cmake/cmake_static_check_smatch.py
|
||||
|
||||
check_spelling_py:
|
||||
cd $(BUILD_DIR) ; PYTHONIOENCODING=utf_8 python3.2 $(BLENDER_DIR)/source/tools/spell_check_source.py $(BLENDER_DIR)/release/scripts
|
||||
|
||||
|
73
build_files/cmake/cmake_static_check_smatch.py
Normal file
73
build_files/cmake/cmake_static_check_smatch.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3.2
|
||||
|
||||
# ***** 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.
|
||||
#
|
||||
# Contributor(s): Campbell Barton
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
CHECKER_IGNORE_PREFIX = [
|
||||
"extern",
|
||||
"intern/moto",
|
||||
]
|
||||
|
||||
CHECKER_BIN = "smatch"
|
||||
CHECKER_ARGS = [
|
||||
"--full-path",
|
||||
"--two-passes",
|
||||
]
|
||||
|
||||
import project_source_info
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
source_info = project_source_info.build_info(use_cxx=False, ignore_prefix_list=CHECKER_IGNORE_PREFIX)
|
||||
|
||||
check_commands = []
|
||||
for c, inc_dirs, defs in source_info:
|
||||
|
||||
cmd = ([CHECKER_BIN] +
|
||||
CHECKER_ARGS +
|
||||
[c] +
|
||||
[("-I%s" % i) for i in inc_dirs] +
|
||||
[("-D%s" % d) for d in defs]
|
||||
)
|
||||
|
||||
check_commands.append((c, cmd))
|
||||
|
||||
def my_process(i, c, cmd):
|
||||
percent = 100.0 * (i / (len(check_commands) - 1))
|
||||
percent_str = "[" + ("%.2f]" % percent).rjust(7) + " %:"
|
||||
|
||||
sys.stdout.flush()
|
||||
sys.stdout.write("%s %s\n" % (percent_str, c))
|
||||
|
||||
return subprocess.Popen(cmd)
|
||||
|
||||
process_functions = []
|
||||
for i, (c, cmd) in enumerate(check_commands):
|
||||
process_functions.append((my_process, (i, c, cmd)))
|
||||
|
||||
project_source_info.queue_processes(process_functions)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@@ -27,7 +27,10 @@ macro(list_insert_after
|
||||
list_id item_check item_add
|
||||
)
|
||||
set(_index)
|
||||
list(FIND ${list_id} "${item_check}" _index)
|
||||
list(FIND "${list_id}" "${item_check}" _index)
|
||||
if("${_index}" MATCHES "-1")
|
||||
message(FATAL_ERROR "'${list_id}' doesn't contain '${item_check}'")
|
||||
endif()
|
||||
math(EXPR _index "${_index} + 1")
|
||||
list(INSERT ${list_id} "${_index}" ${item_add})
|
||||
unset(_index)
|
||||
@@ -37,7 +40,10 @@ macro(list_insert_before
|
||||
list_id item_check item_add
|
||||
)
|
||||
set(_index)
|
||||
list(FIND ${list_id} "${item_check}" _index)
|
||||
list(FIND "${list_id}" "${item_check}" _index)
|
||||
if("${_index}" MATCHES "-1")
|
||||
message(FATAL_ERROR "'${list_id}' doesn't contain '${item_check}'")
|
||||
endif()
|
||||
list(INSERT ${list_id} "${_index}" ${item_add})
|
||||
unset(_index)
|
||||
endmacro()
|
||||
@@ -367,6 +373,9 @@ macro(setup_liblinks
|
||||
if(WITH_MOD_CLOTH_ELTOPO)
|
||||
target_link_libraries(${target} ${LAPACK_LIBRARIES})
|
||||
endif()
|
||||
if(WITH_CYCLES_OSL)
|
||||
target_link_libraries(${target} ${OSL_LIBRARIES})
|
||||
endif()
|
||||
if(WIN32 AND NOT UNIX)
|
||||
target_link_libraries(${target} ${PTHREADS_LIBRARIES})
|
||||
endif()
|
||||
|
@@ -172,7 +172,7 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse']
|
||||
#CUDA
|
||||
WITH_BF_CYCLES_CUDA_BINARIES = False
|
||||
#BF_CYCLES_CUDA_NVCC = "" # Path to the nvidia compiler
|
||||
BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_20', 'sm_21'] # don't build sm_13 until the compile can fit in 32bit process again :)
|
||||
BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
|
||||
|
||||
##
|
||||
CC = 'gcc'
|
||||
|
@@ -151,7 +151,7 @@ BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
|
||||
WITH_BF_CYCLES = True
|
||||
WITH_BF_CYCLES_CUDA_BINARIES = False
|
||||
BF_CYCLES_CUDA_NVCC = "" # Path to the NVIDIA CUDA compiler
|
||||
BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21']
|
||||
BF_CYCLES_CUDA_BINARIES_ARCH = ['sm_13', 'sm_20', 'sm_21', 'sm_30']
|
||||
|
||||
WITH_BF_OIIO = True
|
||||
BF_OIIO = LIBDIR + '/openimageio'
|
||||
|
@@ -851,7 +851,7 @@ def pymodule2sphinx(basepath, module_name, module, title):
|
||||
elif value_type in (bool, int, float, str, tuple):
|
||||
# constant, not much fun we can do here except to list it.
|
||||
# TODO, figure out some way to document these!
|
||||
#fw(".. data:: %s\n\n" % attribute)
|
||||
fw(".. data:: %s\n\n" % attribute)
|
||||
write_indented_lines(" ", fw, "constant value %s" % repr(value), False)
|
||||
fw("\n")
|
||||
else:
|
||||
|
2
extern/bullet2/CMakeLists.txt
vendored
2
extern/bullet2/CMakeLists.txt
vendored
@@ -314,6 +314,7 @@ set(SRC
|
||||
src/BulletDynamics/Character/btKinematicCharacterController.h
|
||||
|
||||
src/BulletSoftBody/btSoftBody.h
|
||||
src/BulletSoftBody/btSoftBodyInternals.h
|
||||
src/BulletSoftBody/btSoftBodyData.h
|
||||
src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
|
||||
src/BulletSoftBody/btSoftBodyHelpers.h
|
||||
@@ -355,6 +356,7 @@ set(SRC
|
||||
|
||||
src/btBulletCollisionCommon.h
|
||||
src/btBulletDynamicsCommon.h
|
||||
src/Bullet-C-Api.h
|
||||
)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
5
extern/libmv/third_party/ceres/SConscript
vendored
5
extern/libmv/third_party/ceres/SConscript
vendored
@@ -25,6 +25,11 @@ defs.append('CERES_RESTRICT_SCHUR_SPECIALIZATION')
|
||||
|
||||
incs = '. ../../ ../../../Eigen3 ./include ./internal ../gflags'
|
||||
|
||||
# work around broken hashtable in 10.5 SDK
|
||||
if env['OURPLATFORM'] == 'darwin' and env['WITH_BF_BOOST']:
|
||||
incs += ' ' + env['BF_BOOST_INC']
|
||||
defs.append('CERES_HASH_BOOST')
|
||||
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'):
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'):
|
||||
incs += ' ../msinttypes'
|
||||
|
@@ -33,6 +33,10 @@
|
||||
#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_
|
||||
#define CERES_INTERNAL_COLLECTIONS_PORT_H_
|
||||
|
||||
#ifdef CERES_HASH_BOOST
|
||||
#include <boost/tr1/unordered_map.hpp>
|
||||
#include <boost/tr1/unordered_set.hpp>
|
||||
#else
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -40,6 +44,8 @@
|
||||
#include <tr1/unordered_map>
|
||||
#include <tr1/unordered_set>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <utility>
|
||||
#include "ceres/integral_types.h"
|
||||
#include "ceres/internal/port.h"
|
||||
@@ -118,7 +124,11 @@ CERES_HASH_NAMESPACE_START
|
||||
|
||||
// Hasher for STL pairs. Requires hashers for both members to be defined.
|
||||
template<typename T>
|
||||
#ifdef CERES_HASH_BOOST
|
||||
struct hash {
|
||||
#else
|
||||
struct hash<pair<T, T> > {
|
||||
#endif
|
||||
size_t operator()(const pair<T, T>& p) const {
|
||||
size_t h1 = hash<T>()(p.first);
|
||||
size_t h2 = hash<T>()(p.second);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -56,8 +56,8 @@ typedef struct
|
||||
typedef void AUD_Handle;
|
||||
typedef void AUD_Device;
|
||||
typedef void AUD_SEntry;
|
||||
typedef float (*AUD_volumeFunction)(void*, void*, float);
|
||||
typedef void (*AUD_syncFunction)(void*, int, float);
|
||||
typedef float (*AUD_volumeFunction)(void *, void *, float);
|
||||
typedef void (*AUD_syncFunction)(void *, int, float);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -94,14 +94,14 @@ extern void AUD_unlock(void);
|
||||
* \param sound The sound to get the info about.
|
||||
* \return The AUD_SoundInfo structure with filled in data.
|
||||
*/
|
||||
extern AUD_SoundInfo AUD_getInfo(AUD_Sound* sound);
|
||||
extern AUD_SoundInfo AUD_getInfo(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Loads a sound file.
|
||||
* \param filename The filename of the sound file.
|
||||
* \return A handle of the sound file.
|
||||
*/
|
||||
extern AUD_Sound* AUD_load(const char* filename);
|
||||
extern AUD_Sound *AUD_load(const char *filename);
|
||||
|
||||
/**
|
||||
* Loads a sound file.
|
||||
@@ -109,21 +109,21 @@ extern AUD_Sound* AUD_load(const char* filename);
|
||||
* \param size The size of the buffer.
|
||||
* \return A handle of the sound file.
|
||||
*/
|
||||
extern AUD_Sound* AUD_loadBuffer(unsigned char* buffer, int size);
|
||||
extern AUD_Sound *AUD_loadBuffer(unsigned char *buffer, int size);
|
||||
|
||||
/**
|
||||
* Buffers a sound.
|
||||
* \param sound The sound to buffer.
|
||||
* \return A handle of the sound buffer.
|
||||
*/
|
||||
extern AUD_Sound* AUD_bufferSound(AUD_Sound* sound);
|
||||
extern AUD_Sound *AUD_bufferSound(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Rechannels the sound to be mono.
|
||||
* \param sound The sound to rechannel.
|
||||
* \return The mono sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_monoSound(AUD_Sound* sound);
|
||||
extern AUD_Sound *AUD_monoSound(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Delays a sound.
|
||||
@@ -131,7 +131,7 @@ extern AUD_Sound* AUD_monoSound(AUD_Sound* sound);
|
||||
* \param delay The delay in seconds.
|
||||
* \return A handle of the delayed sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay);
|
||||
extern AUD_Sound *AUD_delaySound(AUD_Sound *sound, float delay);
|
||||
|
||||
/**
|
||||
* Limits a sound.
|
||||
@@ -140,21 +140,21 @@ extern AUD_Sound* AUD_delaySound(AUD_Sound* sound, float delay);
|
||||
* \param end The stop time in seconds.
|
||||
* \return A handle of the limited sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_limitSound(AUD_Sound* sound, float start, float end);
|
||||
extern AUD_Sound *AUD_limitSound(AUD_Sound *sound, float start, float end);
|
||||
|
||||
/**
|
||||
* Ping pongs a sound.
|
||||
* \param sound The sound to ping pong.
|
||||
* \return A handle of the ping pong sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_pingpongSound(AUD_Sound* sound);
|
||||
extern AUD_Sound *AUD_pingpongSound(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Loops a sound.
|
||||
* \param sound The sound to loop.
|
||||
* \return A handle of the looped sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
|
||||
extern AUD_Sound *AUD_loopSound(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Sets a remaining loop count of a looping sound that currently plays.
|
||||
@@ -162,20 +162,20 @@ extern AUD_Sound* AUD_loopSound(AUD_Sound* sound);
|
||||
* \param loops The count of remaining loops, -1 for infinity.
|
||||
* \return Whether the handle is valid.
|
||||
*/
|
||||
extern int AUD_setLoop(AUD_Handle* handle, int loops);
|
||||
extern int AUD_setLoop(AUD_Handle *handle, int loops);
|
||||
|
||||
/**
|
||||
* Rectifies a sound.
|
||||
* \param sound The sound to rectify.
|
||||
* \return A handle of the rectified sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_rectifySound(AUD_Sound* sound);
|
||||
extern AUD_Sound *AUD_rectifySound(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Unloads a sound of any type.
|
||||
* \param sound The handle of the sound.
|
||||
*/
|
||||
extern void AUD_unload(AUD_Sound* sound);
|
||||
extern void AUD_unload(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Plays back a sound file.
|
||||
@@ -184,28 +184,28 @@ extern void AUD_unload(AUD_Sound* sound);
|
||||
* paused when its end has been reached.
|
||||
* \return A handle to the played back sound.
|
||||
*/
|
||||
extern AUD_Handle* AUD_play(AUD_Sound* sound, int keep);
|
||||
extern AUD_Handle *AUD_play(AUD_Sound *sound, int keep);
|
||||
|
||||
/**
|
||||
* Pauses a played back sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return Whether the handle has been playing or not.
|
||||
*/
|
||||
extern int AUD_pause(AUD_Handle* handle);
|
||||
extern int AUD_pause(AUD_Handle *handle);
|
||||
|
||||
/**
|
||||
* Resumes a paused sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return Whether the handle has been paused or not.
|
||||
*/
|
||||
extern int AUD_resume(AUD_Handle* handle);
|
||||
extern int AUD_resume(AUD_Handle *handle);
|
||||
|
||||
/**
|
||||
* Stops a playing or paused sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return Whether the handle has been valid or not.
|
||||
*/
|
||||
extern int AUD_stop(AUD_Handle* handle);
|
||||
extern int AUD_stop(AUD_Handle *handle);
|
||||
|
||||
/**
|
||||
* Sets the end behaviour of a playing or paused sound.
|
||||
@@ -214,7 +214,7 @@ extern int AUD_stop(AUD_Handle* handle);
|
||||
* paused when its end has been reached.
|
||||
* \return Whether the handle has been valid or not.
|
||||
*/
|
||||
extern int AUD_setKeep(AUD_Handle* handle, int keep);
|
||||
extern int AUD_setKeep(AUD_Handle *handle, int keep);
|
||||
|
||||
/**
|
||||
* Seeks a playing or paused sound.
|
||||
@@ -222,7 +222,7 @@ extern int AUD_setKeep(AUD_Handle* handle, int keep);
|
||||
* \param seekTo From where the sound file should be played back in seconds.
|
||||
* \return Whether the handle has been valid or not.
|
||||
*/
|
||||
extern int AUD_seek(AUD_Handle* handle, float seekTo);
|
||||
extern int AUD_seek(AUD_Handle *handle, float seekTo);
|
||||
|
||||
/**
|
||||
* Retrieves the playback position of a handle.
|
||||
@@ -230,32 +230,32 @@ extern int AUD_seek(AUD_Handle* handle, float seekTo);
|
||||
* \return The current playback position in seconds or 0.0 if the handle is
|
||||
* invalid.
|
||||
*/
|
||||
extern float AUD_getPosition(AUD_Handle* handle);
|
||||
extern float AUD_getPosition(AUD_Handle *handle);
|
||||
|
||||
/**
|
||||
* Returns the status of a playing, paused or stopped sound.
|
||||
* \param handle The handle to the sound.
|
||||
* \return The status of the sound behind the handle.
|
||||
*/
|
||||
extern AUD_Status AUD_getStatus(AUD_Handle* handle);
|
||||
extern AUD_Status AUD_getStatus(AUD_Handle *handle);
|
||||
|
||||
/**
|
||||
* Sets the listener location.
|
||||
* \param location The new location.
|
||||
*/
|
||||
extern int AUD_setListenerLocation(const float* location);
|
||||
extern int AUD_setListenerLocation(const float location[3]);
|
||||
|
||||
/**
|
||||
* Sets the listener velocity.
|
||||
* \param velocity The new velocity.
|
||||
*/
|
||||
extern int AUD_setListenerVelocity(const float* velocity);
|
||||
extern int AUD_setListenerVelocity(const float velocity[3]);
|
||||
|
||||
/**
|
||||
* Sets the listener orientation.
|
||||
* \param orientation The new orientation as quaternion.
|
||||
*/
|
||||
extern int AUD_setListenerOrientation(const float* orientation);
|
||||
extern int AUD_setListenerOrientation(const float orientation[4]);
|
||||
|
||||
/**
|
||||
* Sets the speed of sound.
|
||||
@@ -284,7 +284,7 @@ extern int AUD_setDistanceModel(AUD_DistanceModel model);
|
||||
* \param location The new location.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSourceLocation(AUD_Handle* handle, const float* location);
|
||||
extern int AUD_setSourceLocation(AUD_Handle *handle, const float location[3]);
|
||||
|
||||
/**
|
||||
* Sets the velocity of a source.
|
||||
@@ -292,7 +292,7 @@ extern int AUD_setSourceLocation(AUD_Handle* handle, const float* location);
|
||||
* \param velocity The new velocity.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity);
|
||||
extern int AUD_setSourceVelocity(AUD_Handle *handle, const float velocity[3]);
|
||||
|
||||
/**
|
||||
* Sets the orientation of a source.
|
||||
@@ -300,7 +300,7 @@ extern int AUD_setSourceVelocity(AUD_Handle* handle, const float* velocity);
|
||||
* \param orientation The new orientation as quaternion.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation);
|
||||
extern int AUD_setSourceOrientation(AUD_Handle *handle, const float orientation[4]);
|
||||
|
||||
/**
|
||||
* Sets whether the source location, velocity and orientation are relative
|
||||
@@ -309,7 +309,7 @@ extern int AUD_setSourceOrientation(AUD_Handle* handle, const float* orientation
|
||||
* \param relative Whether the source is relative.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setRelative(AUD_Handle* handle, int relative);
|
||||
extern int AUD_setRelative(AUD_Handle *handle, int relative);
|
||||
|
||||
/**
|
||||
* Sets the maximum volume of a source.
|
||||
@@ -317,7 +317,7 @@ extern int AUD_setRelative(AUD_Handle* handle, int relative);
|
||||
* \param volume The new maximum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setVolumeMaximum(AUD_Handle* handle, float volume);
|
||||
extern int AUD_setVolumeMaximum(AUD_Handle *handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the minimum volume of a source.
|
||||
@@ -325,7 +325,7 @@ extern int AUD_setVolumeMaximum(AUD_Handle* handle, float volume);
|
||||
* \param volume The new minimum volume.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setVolumeMinimum(AUD_Handle* handle, float volume);
|
||||
extern int AUD_setVolumeMinimum(AUD_Handle *handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the maximum distance of a source.
|
||||
@@ -335,7 +335,7 @@ extern int AUD_setVolumeMinimum(AUD_Handle* handle, float volume);
|
||||
* \param distance The new maximum distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDistanceMaximum(AUD_Handle* handle, float distance);
|
||||
extern int AUD_setDistanceMaximum(AUD_Handle *handle, float distance);
|
||||
|
||||
/**
|
||||
* Sets the reference distance of a source.
|
||||
@@ -343,7 +343,7 @@ extern int AUD_setDistanceMaximum(AUD_Handle* handle, float distance);
|
||||
* \param distance The new reference distance.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDistanceReference(AUD_Handle* handle, float distance);
|
||||
extern int AUD_setDistanceReference(AUD_Handle *handle, float distance);
|
||||
|
||||
/**
|
||||
* Sets the attenuation of a source.
|
||||
@@ -352,7 +352,7 @@ extern int AUD_setDistanceReference(AUD_Handle* handle, float distance);
|
||||
* \param factor The new attenuation.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setAttenuation(AUD_Handle* handle, float factor);
|
||||
extern int AUD_setAttenuation(AUD_Handle *handle, float factor);
|
||||
|
||||
/**
|
||||
* Sets the outer angle of the cone of a source.
|
||||
@@ -360,7 +360,7 @@ extern int AUD_setAttenuation(AUD_Handle* handle, float factor);
|
||||
* \param angle The new outer angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeAngleOuter(AUD_Handle* handle, float angle);
|
||||
extern int AUD_setConeAngleOuter(AUD_Handle *handle, float angle);
|
||||
|
||||
/**
|
||||
* Sets the inner angle of the cone of a source.
|
||||
@@ -368,7 +368,7 @@ extern int AUD_setConeAngleOuter(AUD_Handle* handle, float angle);
|
||||
* \param angle The new inner angle of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeAngleInner(AUD_Handle* handle, float angle);
|
||||
extern int AUD_setConeAngleInner(AUD_Handle *handle, float angle);
|
||||
|
||||
/**
|
||||
* Sets the outer volume of the cone of a source.
|
||||
@@ -378,7 +378,7 @@ extern int AUD_setConeAngleInner(AUD_Handle* handle, float angle);
|
||||
* \param volume The new outer volume of the cone.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume);
|
||||
extern int AUD_setConeVolumeOuter(AUD_Handle *handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the volume of a played back sound.
|
||||
@@ -386,7 +386,7 @@ extern int AUD_setConeVolumeOuter(AUD_Handle* handle, float volume);
|
||||
* \param volume The new volume, must be between 0.0 and 1.0.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSoundVolume(AUD_Handle* handle, float volume);
|
||||
extern int AUD_setSoundVolume(AUD_Handle *handle, float volume);
|
||||
|
||||
/**
|
||||
* Sets the pitch of a played back sound.
|
||||
@@ -394,14 +394,14 @@ extern int AUD_setSoundVolume(AUD_Handle* handle, float volume);
|
||||
* \param pitch The new pitch.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setSoundPitch(AUD_Handle* handle, float pitch);
|
||||
extern int AUD_setSoundPitch(AUD_Handle *handle, float pitch);
|
||||
|
||||
/**
|
||||
* Opens a read device, with which audio data can be read.
|
||||
* \param specs The specification of the audio data.
|
||||
* \return A device handle.
|
||||
*/
|
||||
extern AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs);
|
||||
extern AUD_Device *AUD_openReadDevice(AUD_DeviceSpecs specs);
|
||||
|
||||
/**
|
||||
* Sets the main volume of a device.
|
||||
@@ -409,7 +409,7 @@ extern AUD_Device* AUD_openReadDevice(AUD_DeviceSpecs specs);
|
||||
* \param volume The new volume, must be between 0.0 and 1.0.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern int AUD_setDeviceVolume(AUD_Device* device, float volume);
|
||||
extern int AUD_setDeviceVolume(AUD_Device *device, float volume);
|
||||
|
||||
/**
|
||||
* Plays back a sound file through a read device.
|
||||
@@ -418,7 +418,7 @@ extern int AUD_setDeviceVolume(AUD_Device* device, float volume);
|
||||
* \param seek The position where the sound should be seeked to.
|
||||
* \return A handle to the played back sound.
|
||||
*/
|
||||
extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float seek);
|
||||
extern AUD_Handle *AUD_playDevice(AUD_Device *device, AUD_Sound *sound, float seek);
|
||||
|
||||
/**
|
||||
* Reads the next samples into the supplied buffer.
|
||||
@@ -429,23 +429,23 @@ extern AUD_Handle* AUD_playDevice(AUD_Device* device, AUD_Sound* sound, float se
|
||||
* played back currently, in that case the buffer is filled with
|
||||
* silence.
|
||||
*/
|
||||
extern int AUD_readDevice(AUD_Device* device, data_t* buffer, int length);
|
||||
extern int AUD_readDevice(AUD_Device *device, data_t *buffer, int length);
|
||||
|
||||
/**
|
||||
* Closes a read device.
|
||||
* \param device The read device.
|
||||
*/
|
||||
extern void AUD_closeReadDevice(AUD_Device* device);
|
||||
extern void AUD_closeReadDevice(AUD_Device *device);
|
||||
|
||||
/**
|
||||
* Reads a sound file into a newly created float buffer.
|
||||
* The sound is therefore bandpassed, rectified and resampled.
|
||||
*/
|
||||
extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
|
||||
extern float *AUD_readSoundBuffer(const char *filename, float low, float high,
|
||||
float attack, float release, float threshold,
|
||||
int accumulate, int additive, int square,
|
||||
float sthreshold, double samplerate,
|
||||
int* length);
|
||||
int *length);
|
||||
|
||||
/**
|
||||
* Pauses a playing sound after a specific amount of time.
|
||||
@@ -453,7 +453,7 @@ extern float* AUD_readSoundBuffer(const char* filename, float low, float high,
|
||||
* \param seconds The time in seconds.
|
||||
* \return The silence handle.
|
||||
*/
|
||||
extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds);
|
||||
extern AUD_Handle *AUD_pauseAfter(AUD_Handle *handle, float seconds);
|
||||
|
||||
/**
|
||||
* Creates a new sequenced sound scene.
|
||||
@@ -461,27 +461,27 @@ extern AUD_Handle* AUD_pauseAfter(AUD_Handle* handle, float seconds);
|
||||
* \param muted Whether the scene is muted.
|
||||
* \return The new sound scene.
|
||||
*/
|
||||
extern AUD_Sound* AUD_createSequencer(float fps, int muted);
|
||||
extern AUD_Sound *AUD_createSequencer(float fps, int muted);
|
||||
|
||||
/**
|
||||
* Deletes a sound scene.
|
||||
* \param sequencer The sound scene.
|
||||
*/
|
||||
extern void AUD_destroySequencer(AUD_Sound* sequencer);
|
||||
extern void AUD_destroySequencer(AUD_Sound *sequencer);
|
||||
|
||||
/**
|
||||
* Sets the muting state of the scene.
|
||||
* \param sequencer The sound scene.
|
||||
* \param muted Whether the scene is muted.
|
||||
*/
|
||||
extern void AUD_setSequencerMuted(AUD_Sound* sequencer, int muted);
|
||||
extern void AUD_setSequencerMuted(AUD_Sound *sequencer, int muted);
|
||||
|
||||
/**
|
||||
* Sets the scene's FPS.
|
||||
* \param sequencer The sound scene.
|
||||
* \param fps The new FPS.
|
||||
*/
|
||||
extern void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps);
|
||||
extern void AUD_setSequencerFPS(AUD_Sound *sequencer, float fps);
|
||||
|
||||
/**
|
||||
* Adds a new entry to the scene.
|
||||
@@ -492,7 +492,7 @@ extern void AUD_setSequencerFPS(AUD_Sound* sequencer, float fps);
|
||||
* \param skip How much seconds should be skipped at the beginning.
|
||||
* \return The entry added.
|
||||
*/
|
||||
extern AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound,
|
||||
extern AUD_SEntry *AUD_addSequence(AUD_Sound *sequencer, AUD_Sound *sound,
|
||||
float begin, float end, float skip);
|
||||
|
||||
/**
|
||||
@@ -500,7 +500,7 @@ extern AUD_SEntry* AUD_addSequence(AUD_Sound* sequencer, AUD_Sound* sound,
|
||||
* \param sequencer The sound scene.
|
||||
* \param entry The entry to remove.
|
||||
*/
|
||||
extern void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry);
|
||||
extern void AUD_removeSequence(AUD_Sound *sequencer, AUD_SEntry *entry);
|
||||
|
||||
/**
|
||||
* Moves the entry.
|
||||
@@ -509,14 +509,14 @@ extern void AUD_removeSequence(AUD_Sound* sequencer, AUD_SEntry* entry);
|
||||
* \param end The new end time or a negative value if unknown.
|
||||
* \param skip How many seconds to skip at the beginning.
|
||||
*/
|
||||
extern void AUD_moveSequence(AUD_SEntry* entry, float begin, float end, float skip);
|
||||
extern void AUD_moveSequence(AUD_SEntry *entry, float begin, float end, float skip);
|
||||
|
||||
/**
|
||||
* Sets the muting state of the entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param mute Whether the entry should be muted or not.
|
||||
*/
|
||||
extern void AUD_muteSequence(AUD_SEntry* entry, char mute);
|
||||
extern void AUD_muteSequence(AUD_SEntry *entry, char mute);
|
||||
|
||||
/**
|
||||
* Sets whether the entrie's location, velocity and orientation are relative
|
||||
@@ -525,14 +525,14 @@ extern void AUD_muteSequence(AUD_SEntry* entry, char mute);
|
||||
* \param relative Whether the source is relative.
|
||||
* \return Whether the action succeeded.
|
||||
*/
|
||||
extern void AUD_setRelativeSequence(AUD_SEntry* entry, char relative);
|
||||
extern void AUD_setRelativeSequence(AUD_SEntry *entry, char relative);
|
||||
|
||||
/**
|
||||
* Sets the sound of the entry.
|
||||
* \param entry The sequenced entry.
|
||||
* \param sound The new sound.
|
||||
*/
|
||||
extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound);
|
||||
extern void AUD_updateSequenceSound(AUD_SEntry *entry, AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Writes animation data to a sequenced entry.
|
||||
@@ -542,7 +542,7 @@ extern void AUD_updateSequenceSound(AUD_SEntry* entry, AUD_Sound* sound);
|
||||
* \param data The data to write.
|
||||
* \param animated Whether the attribute is animated.
|
||||
*/
|
||||
extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
|
||||
extern void AUD_setSequenceAnimData(AUD_SEntry *entry, AUD_AnimateablePropertyType type, int frame, float *data, char animated);
|
||||
|
||||
/**
|
||||
* Writes animation data to a sequenced entry.
|
||||
@@ -552,7 +552,7 @@ extern void AUD_setSequenceAnimData(AUD_SEntry* entry, AUD_AnimateablePropertyTy
|
||||
* \param data The data to write.
|
||||
* \param animated Whether the attribute is animated.
|
||||
*/
|
||||
extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateablePropertyType type, int frame, float* data, char animated);
|
||||
extern void AUD_setSequencerAnimData(AUD_Sound *sequencer, AUD_AnimateablePropertyType type, int frame, float *data, char animated);
|
||||
|
||||
/**
|
||||
* Updates all non-animated parameters of the entry.
|
||||
@@ -566,7 +566,7 @@ extern void AUD_setSequencerAnimData(AUD_Sound* sequencer, AUD_AnimateableProper
|
||||
* \param cone_angle_inner The inner cone opening angle.
|
||||
* \param cone_volume_outer The volume outside the outer cone.
|
||||
*/
|
||||
extern void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float volume_min,
|
||||
extern void AUD_updateSequenceData(AUD_SEntry *entry, float volume_max, float volume_min,
|
||||
float distance_max, float distance_reference, float attenuation,
|
||||
float cone_angle_outer, float cone_angle_inner, float cone_volume_outer);
|
||||
|
||||
@@ -577,7 +577,7 @@ extern void AUD_updateSequenceData(AUD_SEntry* entry, float volume_max, float vo
|
||||
* \param factor The doppler factor to control the effect's strength.
|
||||
* \param model The distance model for distance calculation.
|
||||
*/
|
||||
extern void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound,
|
||||
extern void AUD_updateSequencerData(AUD_Sound *sequencer, float speed_of_sound,
|
||||
float factor, AUD_DistanceModel model);
|
||||
|
||||
/**
|
||||
@@ -585,28 +585,28 @@ extern void AUD_updateSequencerData(AUD_Sound* sequencer, float speed_of_sound,
|
||||
* current playback device.
|
||||
* \param sequencer The sound scene.
|
||||
*/
|
||||
extern void AUD_setSequencerDeviceSpecs(AUD_Sound* sequencer);
|
||||
extern void AUD_setSequencerDeviceSpecs(AUD_Sound *sequencer);
|
||||
|
||||
/**
|
||||
* Sets the audio output specification of the sound scene.
|
||||
* \param sequencer The sound scene.
|
||||
* \param specs The new specification.
|
||||
*/
|
||||
extern void AUD_setSequencerSpecs(AUD_Sound* sequencer, AUD_Specs specs);
|
||||
extern void AUD_setSequencerSpecs(AUD_Sound *sequencer, AUD_Specs specs);
|
||||
|
||||
/**
|
||||
* Seeks sequenced sound scene playback.
|
||||
* \param handle Playback handle.
|
||||
* \param time Time in seconds to seek to.
|
||||
*/
|
||||
extern void AUD_seekSequencer(AUD_Handle* handle, float time);
|
||||
extern void AUD_seekSequencer(AUD_Handle *handle, float time);
|
||||
|
||||
/**
|
||||
* Returns the current sound scene playback time.
|
||||
* \param handle Playback handle.
|
||||
* \return The playback time in seconds.
|
||||
*/
|
||||
extern float AUD_getSequencerPosition(AUD_Handle* handle);
|
||||
extern float AUD_getSequencerPosition(AUD_Handle *handle);
|
||||
|
||||
/**
|
||||
* Starts the playback of jack transport if possible.
|
||||
@@ -624,7 +624,7 @@ extern void AUD_stopPlayback(void);
|
||||
* \param function The callback function.
|
||||
* \param data The data parameter for the callback.
|
||||
*/
|
||||
extern void AUD_setSyncCallback(AUD_syncFunction function, void* data);
|
||||
extern void AUD_setSyncCallback(AUD_syncFunction function, void *data);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -641,32 +641,32 @@ extern int AUD_doesPlayback(void);
|
||||
* \param samples_per_second How many samples to read per second of the sound.
|
||||
* \return How many samples really have been read. Always <= length.
|
||||
*/
|
||||
extern int AUD_readSound(AUD_Sound* sound, sample_t* buffer, int length, int samples_per_second);
|
||||
extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second);
|
||||
|
||||
/**
|
||||
* Copies a sound.
|
||||
* \param sound Sound to copy.
|
||||
* \return Copied sound.
|
||||
*/
|
||||
extern AUD_Sound* AUD_copy(AUD_Sound* sound);
|
||||
extern AUD_Sound *AUD_copy(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Frees a handle.
|
||||
* \param channel Handle to free.
|
||||
*/
|
||||
extern void AUD_freeHandle(AUD_Handle* channel);
|
||||
extern void AUD_freeHandle(AUD_Handle *channel);
|
||||
|
||||
/**
|
||||
* Creates a new set.
|
||||
* \return The new set.
|
||||
*/
|
||||
extern void* AUD_createSet(void);
|
||||
extern void *AUD_createSet(void);
|
||||
|
||||
/**
|
||||
* Deletes a set.
|
||||
* \param set The set to delete.
|
||||
*/
|
||||
extern void AUD_destroySet(void* set);
|
||||
extern void AUD_destroySet(void *set);
|
||||
|
||||
/**
|
||||
* Removes an entry from a set.
|
||||
@@ -674,21 +674,21 @@ extern void AUD_destroySet(void* set);
|
||||
* \param entry The entry to remove.
|
||||
* \return Whether the entry was in the set or not.
|
||||
*/
|
||||
extern char AUD_removeSet(void* set, void* entry);
|
||||
extern char AUD_removeSet(void *set, void *entry);
|
||||
|
||||
/**
|
||||
* Adds a new entry to a set.
|
||||
* \param set The set work on.
|
||||
* \param entry The entry to add.
|
||||
*/
|
||||
extern void AUD_addSet(void* set, void* entry);
|
||||
extern void AUD_addSet(void *set, void *entry);
|
||||
|
||||
/**
|
||||
* Removes one entry from a set and returns it.
|
||||
* \param set The set work on.
|
||||
* \return The entry or NULL if the set is empty.
|
||||
*/
|
||||
extern void* AUD_getSet(void* set);
|
||||
extern void *AUD_getSet(void *set);
|
||||
|
||||
/**
|
||||
* Mixes a sound down into a file.
|
||||
@@ -703,7 +703,10 @@ extern void* AUD_getSet(void* set);
|
||||
* \param bitrate The bitrate for encoding.
|
||||
* \return An error message or NULL in case of success.
|
||||
*/
|
||||
extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
|
||||
extern const char *AUD_mixdown(AUD_Sound *sound, unsigned int start, unsigned int length,
|
||||
unsigned int buffersize, const char *filename,
|
||||
AUD_DeviceSpecs specs, AUD_Container format,
|
||||
AUD_Codec codec, unsigned int bitrate);
|
||||
|
||||
/**
|
||||
* Mixes a sound down into multiple files.
|
||||
@@ -718,7 +721,10 @@ extern const char* AUD_mixdown(AUD_Sound* sound, unsigned int start, unsigned in
|
||||
* \param bitrate The bitrate for encoding.
|
||||
* \return An error message or NULL in case of success.
|
||||
*/
|
||||
extern const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start, unsigned int length, unsigned int buffersize, const char* filename, AUD_DeviceSpecs specs, AUD_Container format, AUD_Codec codec, unsigned int bitrate);
|
||||
extern const char *AUD_mixdown_per_channel(AUD_Sound *sound, unsigned int start, unsigned int length,
|
||||
unsigned int buffersize, const char *filename,
|
||||
AUD_DeviceSpecs specs, AUD_Container format,
|
||||
AUD_Codec codec, unsigned int bitrate);
|
||||
|
||||
/**
|
||||
* Opens a read device and prepares it for mixdown of the sound scene.
|
||||
@@ -728,7 +734,7 @@ extern const char* AUD_mixdown_per_channel(AUD_Sound* sound, unsigned int start,
|
||||
* \param start The start time of the mixdown in the sound scene.
|
||||
* \return The read device for the mixdown.
|
||||
*/
|
||||
extern AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* sequencer, float volume, float start);
|
||||
extern AUD_Device *AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound *sequencer, float volume, float start);
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
/**
|
||||
@@ -736,14 +742,14 @@ extern AUD_Device* AUD_openMixdownDevice(AUD_DeviceSpecs specs, AUD_Sound* seque
|
||||
* \param sound The sound factory.
|
||||
* \return The python factory.
|
||||
*/
|
||||
extern void* AUD_getPythonFactory(AUD_Sound* sound);
|
||||
extern void *AUD_getPythonFactory(AUD_Sound *sound);
|
||||
|
||||
/**
|
||||
* Retrieves the sound factory of a python factory.
|
||||
* \param sound The python factory.
|
||||
* \return The sound factory.
|
||||
*/
|
||||
extern AUD_Sound* AUD_getPythonSound(void* sound);
|
||||
extern AUD_Sound *AUD_getPythonSound(void *sound);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -763,7 +769,7 @@ AUD_Reference<AUD_IDevice> AUD_getDevice();
|
||||
* Returns the current playback 3D device.
|
||||
* \return The playback 3D device.
|
||||
*/
|
||||
AUD_I3DDevice* AUD_get3DDevice();
|
||||
AUD_I3DDevice *AUD_get3DDevice();
|
||||
#endif
|
||||
|
||||
#endif //__AUD_C_API_H__
|
||||
|
@@ -22,7 +22,7 @@
|
||||
* ***** END GPL LICENSE BLOCK *****
|
||||
*/
|
||||
|
||||
/** \file audaspace/intern/AUD_Reference.cpp
|
||||
/** \file audaspace/intern/AUD_ReferenceHandler.cpp
|
||||
* \ingroup audaspaceintern
|
||||
*/
|
||||
|
||||
|
@@ -20,8 +20,8 @@ elseif(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math")
|
||||
endif()
|
||||
|
||||
# for OSL, not needed yet
|
||||
# set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
|
||||
# for OSL
|
||||
set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
|
||||
# set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
|
||||
|
||||
# Definitions and Includes
|
||||
|
@@ -66,12 +66,13 @@ static void session_print(const string& str)
|
||||
|
||||
static void session_print_status()
|
||||
{
|
||||
int sample;
|
||||
int sample, tile;
|
||||
double total_time, sample_time;
|
||||
string status, substatus;
|
||||
|
||||
/* get status */
|
||||
options.session->progress.get_sample(sample, total_time, sample_time);
|
||||
sample = options.session->progress.get_sample();
|
||||
options.session->progress.get_tile(tile, total_time, sample_time);
|
||||
options.session->progress.get_status(status, substatus);
|
||||
|
||||
if(substatus != "")
|
||||
@@ -111,7 +112,7 @@ static void session_init()
|
||||
|
||||
static void scene_init(int width, int height)
|
||||
{
|
||||
options.scene = new Scene(options.scene_params);
|
||||
options.scene = new Scene(options.scene_params, options.session_params.device);
|
||||
xml_read_file(options.scene, options.filepath.c_str());
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
@@ -147,11 +148,12 @@ static void display_info(Progress& progress)
|
||||
latency = (elapsed - last);
|
||||
last = elapsed;
|
||||
|
||||
int sample;
|
||||
int sample, tile;
|
||||
double total_time, sample_time;
|
||||
string status, substatus;
|
||||
|
||||
progress.get_sample(sample, total_time, sample_time);
|
||||
sample = progress.get_sample();
|
||||
progress.get_tile(tile, total_time, sample_time);
|
||||
progress.get_status(status, substatus);
|
||||
|
||||
if(substatus != "")
|
||||
@@ -270,6 +272,9 @@ static void options_parse(int argc, const char **argv)
|
||||
options.scene_params.shadingsystem = SceneParams::OSL;
|
||||
else if(ssname == "svm")
|
||||
options.scene_params.shadingsystem = SceneParams::SVM;
|
||||
|
||||
/* Progressive rendering */
|
||||
options.session_params.progressive = true;
|
||||
|
||||
/* find matching device */
|
||||
DeviceType device_type = Device::type_from_string(devicename.c_str());
|
||||
|
@@ -379,6 +379,9 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
|
||||
else if(string_iequals(node.name(), "checker_texture")) {
|
||||
snode = new CheckerTextureNode();
|
||||
}
|
||||
else if(string_iequals(node.name(), "brick_texture")) {
|
||||
snode = new BrickTextureNode();
|
||||
}
|
||||
else if(string_iequals(node.name(), "gradient_texture")) {
|
||||
GradientTextureNode *blend = new GradientTextureNode();
|
||||
xml_read_enum(&blend->type, GradientTextureNode::type_enum, node, "type");
|
||||
@@ -484,6 +487,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
|
||||
else if(string_iequals(node.name(), "mix")) {
|
||||
MixNode *mix = new MixNode();
|
||||
xml_read_enum(&mix->type, MixNode::type_enum, node, "type");
|
||||
xml_read_bool(&mix->use_clamp, node, "use_clamp");
|
||||
snode = mix;
|
||||
}
|
||||
else if(string_iequals(node.name(), "gamma")) {
|
||||
@@ -515,6 +519,7 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
|
||||
else if(string_iequals(node.name(), "math")) {
|
||||
MathNode *math = new MathNode();
|
||||
xml_read_enum(&math->type, MathNode::type_enum, node, "type");
|
||||
xml_read_bool(&math->use_clamp, node, "use_clamp");
|
||||
snode = math;
|
||||
}
|
||||
else if(string_iequals(node.name(), "vector_math")) {
|
||||
|
@@ -241,12 +241,14 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
min=1, max=4096,
|
||||
default=1024,
|
||||
)
|
||||
cls.debug_min_size = IntProperty(
|
||||
name="Min Size",
|
||||
description="",
|
||||
min=1, max=4096,
|
||||
default=64,
|
||||
|
||||
cls.resolution_divider = IntProperty(
|
||||
name="Resolution Divider",
|
||||
description="For viewport render, the number of lower resolutions to render before the full resolution",
|
||||
min=1, max=512,
|
||||
default=4,
|
||||
)
|
||||
|
||||
cls.debug_reset_timeout = FloatProperty(
|
||||
name="Reset timeout",
|
||||
description="",
|
||||
|
@@ -53,19 +53,20 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
|
||||
|
||||
scene = context.scene
|
||||
cscene = scene.cycles
|
||||
device_type = context.user_preferences.system.compute_device_type
|
||||
|
||||
split = layout.split()
|
||||
|
||||
col = split.column()
|
||||
sub = col.column()
|
||||
sub.active = cscene.device == 'CPU'
|
||||
sub.enabled = (device_type == 'NONE' or cscene.device == 'CPU')
|
||||
sub.prop(cscene, "progressive")
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.prop(cscene, "seed")
|
||||
sub.prop(cscene, "sample_clamp")
|
||||
|
||||
if cscene.progressive or cscene.device != 'CPU':
|
||||
if cscene.progressive or (device_type != 'NONE' and cscene.device == 'GPU'):
|
||||
col = split.column()
|
||||
col.label(text="Samples:")
|
||||
sub = col.column(align=True)
|
||||
@@ -197,8 +198,13 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.label(text="Tiles:")
|
||||
sub.prop(cscene, "debug_tile_size")
|
||||
sub.prop(cscene, "debug_min_size")
|
||||
|
||||
sub.prop(rd, "parts_x", text="X")
|
||||
sub.prop(rd, "parts_y", text="Y")
|
||||
|
||||
subsub = sub.column()
|
||||
subsub.enabled = not rd.use_border
|
||||
subsub.prop(rd, "use_save_buffers")
|
||||
|
||||
col = split.column()
|
||||
|
||||
@@ -208,6 +214,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
|
||||
sub.prop(cscene, "debug_use_spatial_splits")
|
||||
sub.prop(cscene, "use_cache")
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.label(text="Viewport:")
|
||||
sub.prop(cscene, "resolution_divider")
|
||||
|
||||
|
||||
class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Layers"
|
||||
@@ -920,6 +930,9 @@ def draw_device(self, context):
|
||||
layout.prop(cscene, "device")
|
||||
elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL':
|
||||
layout.prop(cscene, "device")
|
||||
|
||||
if cscene.feature_set == 'EXPERIMENTAL' and cscene.device == 'CPU' and engine.with_osl():
|
||||
layout.prop(cscene, "shading_system")
|
||||
|
||||
|
||||
def draw_pause(self, context):
|
||||
|
@@ -317,11 +317,11 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion)
|
||||
BL::Mesh::vertices_iterator v;
|
||||
AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST;
|
||||
Attribute *attr_M = mesh->attributes.add(std);
|
||||
float3 *M = attr_M->data_float3();
|
||||
float3 *M = attr_M->data_float3(), *cur_M;
|
||||
size_t i = 0;
|
||||
|
||||
for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < size; ++v, M++, i++)
|
||||
*M = get_float3(v->co());
|
||||
for(b_mesh.vertices.begin(v), cur_M = M; v != b_mesh.vertices.end() && i < size; ++v, cur_M++, i++)
|
||||
*cur_M = get_float3(v->co());
|
||||
|
||||
/* if number of vertices changed, or if coordinates stayed the same, drop it */
|
||||
if(i != size || memcmp(M, &mesh->verts[0], sizeof(float3)*size) == 0)
|
||||
|
@@ -247,11 +247,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
|
||||
scene->object_manager->tag_update(scene);
|
||||
}
|
||||
|
||||
/* updated dupli objects require particle sync */
|
||||
bool need_particle_update = object_need_particle_update(b_ob);
|
||||
|
||||
/* object sync */
|
||||
if(object_updated || (object->mesh && object->mesh->need_update) || need_particle_update) {
|
||||
/* transform comparison should not be needed, but duplis don't work perfect
|
||||
* in the depsgraph and may not signal changes, so this is a workaround */
|
||||
if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
|
||||
object->name = b_ob.name().c_str();
|
||||
object->pass_id = b_ob.pass_index();
|
||||
object->tfm = tfm;
|
||||
@@ -277,10 +276,6 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
|
||||
|
||||
object->particle_id = particle_id;
|
||||
|
||||
/* particle sync */
|
||||
if (need_particle_update)
|
||||
sync_particles(object, b_ob);
|
||||
|
||||
object->tag_update(scene);
|
||||
}
|
||||
}
|
||||
@@ -303,16 +298,18 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
|
||||
/* object loop */
|
||||
BL::Scene::objects_iterator b_ob;
|
||||
BL::Scene b_sce = b_scene;
|
||||
int particle_offset = 0;
|
||||
int particle_offset = 1; /* first particle is dummy for regular, non-instanced objects */
|
||||
|
||||
for(; b_sce; b_sce = b_sce.background_set()) {
|
||||
for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) {
|
||||
bool cancel = false;
|
||||
|
||||
for(; b_sce && !cancel; b_sce = b_sce.background_set()) {
|
||||
for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end() && !cancel; ++b_ob) {
|
||||
bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render();
|
||||
uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), object_is_light(*b_ob));
|
||||
CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, ob_layer);
|
||||
uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob));
|
||||
hide = hide || !(ob_layer & scene_layer);
|
||||
|
||||
if(!hide) {
|
||||
progress.set_status("Synchronizing object", (*b_ob).name());
|
||||
|
||||
int num_particles = object_count_particles(*b_ob);
|
||||
|
||||
@@ -354,10 +351,12 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
|
||||
|
||||
particle_offset += num_particles;
|
||||
}
|
||||
|
||||
cancel = progress.get_cancel();
|
||||
}
|
||||
}
|
||||
|
||||
if(!motion) {
|
||||
if(!cancel && !motion) {
|
||||
sync_background_light();
|
||||
|
||||
/* handle removed data and modified pointers */
|
||||
|
@@ -16,9 +16,9 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "object.h"
|
||||
|
||||
#include "mesh.h"
|
||||
#include "particles.h"
|
||||
|
||||
#include "blender_sync.h"
|
||||
#include "blender_util.h"
|
||||
|
||||
@@ -31,7 +31,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Particles Sync */
|
||||
|
||||
bool BlenderSync::object_need_particle_update(BL::Object b_ob)
|
||||
bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys)
|
||||
{
|
||||
/* Particle data is only needed for
|
||||
* a) Billboard render mode if object's own material uses particle info
|
||||
@@ -41,9 +41,7 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob)
|
||||
*/
|
||||
bool need_update = false;
|
||||
|
||||
BL::Object::particle_systems_iterator b_psys;
|
||||
for (b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
|
||||
switch (b_psys->settings().render_type()) {
|
||||
switch (b_psys.settings().render_type()) {
|
||||
/* XXX not implemented yet!
|
||||
* billboards/strands would become part of the mesh data (?),
|
||||
* so the mesh attributes would store whether particle info is required.
|
||||
@@ -61,7 +59,7 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob)
|
||||
#endif
|
||||
|
||||
case BL::ParticleSettings::render_type_OBJECT: {
|
||||
BL::Object b_dupli_ob = b_psys->settings().dupli_object();
|
||||
BL::Object b_dupli_ob = b_psys.settings().dupli_object();
|
||||
if (b_dupli_ob) {
|
||||
BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data();
|
||||
Mesh *mesh = mesh_map.find(key);
|
||||
@@ -73,7 +71,7 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob)
|
||||
}
|
||||
|
||||
case BL::ParticleSettings::render_type_GROUP: {
|
||||
BL::Group b_dupli_group = b_psys->settings().dupli_group();
|
||||
BL::Group b_dupli_group = b_psys.settings().dupli_group();
|
||||
if (b_dupli_group) {
|
||||
BL::Group::objects_iterator b_gob;
|
||||
for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) {
|
||||
@@ -90,7 +88,6 @@ bool BlenderSync::object_need_particle_update(BL::Object b_ob)
|
||||
default:
|
||||
/* avoid compiler warning */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return need_update;
|
||||
@@ -114,7 +111,19 @@ static bool use_particle_system(BL::ParticleSystem b_psys)
|
||||
|
||||
static bool use_particle(BL::Particle b_pa)
|
||||
{
|
||||
return b_pa.is_exist() && b_pa.is_visible() && b_pa.alive_state()==BL::Particle::alive_state_ALIVE;
|
||||
return b_pa.is_exist() && b_pa.is_visible() &&
|
||||
(b_pa.alive_state()==BL::Particle::alive_state_ALIVE || b_pa.alive_state()==BL::Particle::alive_state_DYING);
|
||||
}
|
||||
|
||||
static int psys_count_particles(BL::ParticleSystem b_psys)
|
||||
{
|
||||
int tot = 0;
|
||||
BL::ParticleSystem::particles_iterator b_pa;
|
||||
for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) {
|
||||
if(use_particle(*b_pa))
|
||||
++tot;
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
int BlenderSync::object_count_particles(BL::Object b_ob)
|
||||
@@ -122,45 +131,88 @@ int BlenderSync::object_count_particles(BL::Object b_ob)
|
||||
int tot = 0;
|
||||
BL::Object::particle_systems_iterator b_psys;
|
||||
for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
|
||||
if (use_particle_system(*b_psys)) {
|
||||
BL::ParticleSystem::particles_iterator b_pa;
|
||||
for(b_psys->particles.begin(b_pa); b_pa != b_psys->particles.end(); ++b_pa) {
|
||||
if(use_particle(*b_pa))
|
||||
++tot;
|
||||
}
|
||||
}
|
||||
if (use_particle_system(*b_psys))
|
||||
tot += psys_count_particles(*b_psys);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
void BlenderSync::sync_particles(Object *ob, BL::Object b_ob)
|
||||
void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys)
|
||||
{
|
||||
int tot = object_count_particles(b_ob);
|
||||
/* depending on settings the psys may not even be rendered */
|
||||
if (!use_particle_system(b_psys))
|
||||
return;
|
||||
|
||||
ob->particles.clear();
|
||||
ob->particles.reserve(tot);
|
||||
/* key to lookup particle system */
|
||||
ParticleSystemKey key(b_ob, b_psys);
|
||||
ParticleSystem *psys;
|
||||
|
||||
int index;
|
||||
BL::Object::particle_systems_iterator b_psys;
|
||||
for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) {
|
||||
if (use_particle_system(*b_psys)) {
|
||||
int pa_index = 0;
|
||||
BL::ParticleSystem::particles_iterator b_pa;
|
||||
for(b_psys->particles.begin(b_pa), index = 0; b_pa != b_psys->particles.end(); ++b_pa, ++index) {
|
||||
if(use_particle(*b_pa)) {
|
||||
Particle pa;
|
||||
|
||||
pa.index = pa_index;
|
||||
pa.age = b_scene.frame_current() - b_pa->birth_time();
|
||||
pa.lifetime = b_pa->lifetime();
|
||||
|
||||
ob->particles.push_back(pa);
|
||||
}
|
||||
/* test if we need to sync */
|
||||
bool object_updated = false;
|
||||
|
||||
if(particle_system_map.sync(&psys, b_ob, b_ob, key))
|
||||
object_updated = true;
|
||||
|
||||
bool need_update = psys_need_update(b_psys);
|
||||
|
||||
if (object_updated || need_update) {
|
||||
int tot = psys_count_particles(b_psys);
|
||||
psys->particles.clear();
|
||||
psys->particles.reserve(tot);
|
||||
|
||||
int index = 0;
|
||||
BL::ParticleSystem::particles_iterator b_pa;
|
||||
for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) {
|
||||
if(use_particle(*b_pa)) {
|
||||
Particle pa;
|
||||
|
||||
++pa_index;
|
||||
pa.index = index;
|
||||
pa.age = b_scene.frame_current() - b_pa->birth_time();
|
||||
pa.lifetime = b_pa->lifetime();
|
||||
pa.location = get_float3(b_pa->location());
|
||||
pa.rotation = get_float4(b_pa->rotation());
|
||||
pa.size = b_pa->size();
|
||||
pa.velocity = get_float3(b_pa->velocity());
|
||||
pa.angular_velocity = get_float3(b_pa->angular_velocity());
|
||||
|
||||
psys->particles.push_back(pa);
|
||||
}
|
||||
|
||||
++index;
|
||||
}
|
||||
|
||||
psys->tag_update(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderSync::sync_particle_systems()
|
||||
{
|
||||
/* layer data */
|
||||
uint scene_layer = render_layer.scene_layer;
|
||||
|
||||
particle_system_map.pre_sync();
|
||||
|
||||
/* object loop */
|
||||
BL::Scene::objects_iterator b_ob;
|
||||
BL::Scene b_sce = b_scene;
|
||||
|
||||
for(; b_sce; b_sce = b_sce.background_set()) {
|
||||
for(b_sce.objects.begin(b_ob); b_ob != b_sce.objects.end(); ++b_ob) {
|
||||
bool hide = (render_layer.use_viewport_visibility)? b_ob->hide(): b_ob->hide_render();
|
||||
uint ob_layer = get_layer(b_ob->layers(), b_ob->layers_local_view(), render_layer.use_localview, object_is_light(*b_ob));
|
||||
hide = hide || !(ob_layer & scene_layer);
|
||||
|
||||
if(!hide) {
|
||||
BL::Object::particle_systems_iterator b_psys;
|
||||
for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
|
||||
sync_particles(*b_ob, *b_psys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* handle removed data and modified pointers */
|
||||
if(particle_system_map.post_sync())
|
||||
scene->particle_system_manager->tag_update(scene);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -80,6 +80,8 @@ static PyObject *create_func(PyObject *self, PyObject *args)
|
||||
/* create session */
|
||||
BlenderSession *session;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
if(rv3d) {
|
||||
/* interactive session */
|
||||
int width = region.width();
|
||||
@@ -91,7 +93,9 @@ static PyObject *create_func(PyObject *self, PyObject *args)
|
||||
/* offline session */
|
||||
session = new BlenderSession(engine, userpref, data, scene);
|
||||
}
|
||||
|
||||
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
return PyLong_FromVoidPtr(session);
|
||||
}
|
||||
|
||||
@@ -136,9 +140,13 @@ static PyObject *draw_func(PyObject *self, PyObject *args)
|
||||
|
||||
static PyObject *sync_func(PyObject *self, PyObject *value)
|
||||
{
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
|
||||
BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(value);
|
||||
session->synchronize();
|
||||
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
@@ -42,14 +42,13 @@ CCL_NAMESPACE_BEGIN
|
||||
BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b_userpref_,
|
||||
BL::BlendData b_data_, BL::Scene b_scene_)
|
||||
: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_),
|
||||
b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL),
|
||||
b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
|
||||
b_v3d(PointerRNA_NULL), b_rv3d(PointerRNA_NULL)
|
||||
{
|
||||
/* offline render */
|
||||
BL::RenderSettings r = b_scene.render();
|
||||
|
||||
width = (int)(r.resolution_x()*r.resolution_percentage()/100);
|
||||
height = (int)(r.resolution_y()*r.resolution_percentage()/100);
|
||||
width = b_engine.resolution_x();
|
||||
height = b_engine.resolution_y();
|
||||
|
||||
background = true;
|
||||
last_redraw_time = 0.0f;
|
||||
|
||||
@@ -60,7 +59,7 @@ BlenderSession::BlenderSession(BL::RenderEngine b_engine_, BL::UserPreferences b
|
||||
BL::BlendData b_data_, BL::Scene b_scene_,
|
||||
BL::SpaceView3D b_v3d_, BL::RegionView3D b_rv3d_, int width_, int height_)
|
||||
: b_engine(b_engine_), b_userpref(b_userpref_), b_data(b_data_), b_scene(b_scene_),
|
||||
b_v3d(b_v3d_), b_rv3d(b_rv3d_), b_rr(PointerRNA_NULL), b_rlay(PointerRNA_NULL)
|
||||
b_v3d(b_v3d_), b_rv3d(b_rv3d_)
|
||||
{
|
||||
/* 3d view render */
|
||||
width = width_;
|
||||
@@ -80,23 +79,14 @@ BlenderSession::~BlenderSession()
|
||||
void BlenderSession::create_session()
|
||||
{
|
||||
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
|
||||
|
||||
/* reset status/progress */
|
||||
last_status = "";
|
||||
last_progress = -1.0f;
|
||||
|
||||
/* create scene */
|
||||
scene = new Scene(scene_params);
|
||||
|
||||
/* create sync */
|
||||
sync = new BlenderSync(b_data, b_scene, scene, !background);
|
||||
sync->sync_data(b_v3d, b_engine.camera_override());
|
||||
|
||||
if(b_rv3d)
|
||||
sync->sync_view(b_v3d, b_rv3d, width, height);
|
||||
else
|
||||
sync->sync_camera(b_engine.camera_override(), width, height);
|
||||
scene = new Scene(scene_params, session_params.device);
|
||||
|
||||
/* create session */
|
||||
session = new Session(session_params);
|
||||
@@ -105,6 +95,15 @@ void BlenderSession::create_session()
|
||||
session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this));
|
||||
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
|
||||
|
||||
/* create sync */
|
||||
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
|
||||
sync->sync_data(b_v3d, b_engine.camera_override());
|
||||
|
||||
if(b_rv3d)
|
||||
sync->sync_view(b_v3d, b_rv3d, width, height);
|
||||
else
|
||||
sync->sync_camera(b_engine.camera_override(), width, height);
|
||||
|
||||
/* set buffer parameters */
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
@@ -177,35 +176,100 @@ static PassType get_pass_type(BL::RenderPass b_pass)
|
||||
return PASS_NONE;
|
||||
}
|
||||
|
||||
void BlenderSession::render()
|
||||
static BL::RenderResult begin_render_result(BL::RenderEngine b_engine, int x, int y, int w, int h, const char *layername)
|
||||
{
|
||||
/* get buffer parameters */
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
|
||||
int w = buffer_params.width, h = buffer_params.height;
|
||||
|
||||
/* create render result */
|
||||
RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, 0, 0, w, h);
|
||||
RenderResult *rrp = RE_engine_begin_result((RenderEngine*)b_engine.ptr.data, x, y, w, h, layername);
|
||||
PointerRNA rrptr;
|
||||
RNA_pointer_create(NULL, &RNA_RenderResult, rrp, &rrptr);
|
||||
b_rr = BL::RenderResult(rrptr);
|
||||
return BL::RenderResult(rrptr);
|
||||
}
|
||||
|
||||
static void end_render_result(BL::RenderEngine b_engine, BL::RenderResult b_rr, bool cancel = false)
|
||||
{
|
||||
RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data, (int)cancel);
|
||||
}
|
||||
|
||||
void BlenderSession::do_write_update_render_tile(RenderTile& rtile, bool do_update_only)
|
||||
{
|
||||
BufferParams& params = rtile.buffers->params;
|
||||
int x = params.full_x - session->tile_manager.params.full_x;
|
||||
int y = params.full_y - session->tile_manager.params.full_y;
|
||||
int w = params.width;
|
||||
int h = params.height;
|
||||
|
||||
/* get render result */
|
||||
BL::RenderResult b_rr = begin_render_result(b_engine, x, y, w, h, b_rlay_name.c_str());
|
||||
|
||||
/* can happen if the intersected rectangle gives 0 width or height */
|
||||
if (b_rr.ptr.data == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BL::RenderResult::layers_iterator b_single_rlay;
|
||||
b_rr.layers.begin(b_single_rlay);
|
||||
BL::RenderLayer b_rlay = *b_single_rlay;
|
||||
|
||||
if (do_update_only) {
|
||||
/* update only needed */
|
||||
update_render_result(b_rr, b_rlay, rtile);
|
||||
end_render_result(b_engine, b_rr, true);
|
||||
}
|
||||
else {
|
||||
/* write result */
|
||||
write_render_result(b_rr, b_rlay, rtile);
|
||||
end_render_result(b_engine, b_rr);
|
||||
}
|
||||
}
|
||||
|
||||
void BlenderSession::write_render_tile(RenderTile& rtile)
|
||||
{
|
||||
do_write_update_render_tile(rtile, false);
|
||||
}
|
||||
|
||||
void BlenderSession::update_render_tile(RenderTile& rtile)
|
||||
{
|
||||
do_write_update_render_tile(rtile, true);
|
||||
}
|
||||
|
||||
void BlenderSession::render()
|
||||
{
|
||||
/* set callback to write out render results */
|
||||
session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
|
||||
session->update_render_tile_cb = function_bind(&BlenderSession::update_render_tile, this, _1);
|
||||
|
||||
/* get buffer parameters */
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, width, height);
|
||||
|
||||
BL::RenderSettings r = b_scene.render();
|
||||
BL::RenderResult::layers_iterator b_iter;
|
||||
BL::RenderLayers b_rr_layers(r.ptr);
|
||||
|
||||
/* render each layer */
|
||||
for(b_rr.layers.begin(b_iter); b_iter != b_rr.layers.end(); ++b_iter) {
|
||||
/* set layer */
|
||||
b_rlay = *b_iter;
|
||||
BL::RenderSettings r = b_scene.render();
|
||||
BL::RenderSettings::layers_iterator b_iter;
|
||||
|
||||
for(r.layers.begin(b_iter); b_iter != r.layers.end(); ++b_iter) {
|
||||
b_rlay_name = b_iter->name();
|
||||
|
||||
/* temporary render result to find needed passes */
|
||||
BL::RenderResult b_rr = begin_render_result(b_engine, 0, 0, 1, 1, b_rlay_name.c_str());
|
||||
BL::RenderResult::layers_iterator b_single_rlay;
|
||||
b_rr.layers.begin(b_single_rlay);
|
||||
|
||||
/* layer will be missing if it was disabled in the UI */
|
||||
if(b_single_rlay == b_rr.layers.end()) {
|
||||
end_render_result(b_engine, b_rr, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
BL::RenderLayer b_rlay = *b_single_rlay;
|
||||
|
||||
/* add passes */
|
||||
vector<Pass> passes;
|
||||
Pass::add(PASS_COMBINED, passes);
|
||||
|
||||
if(session_params.device.advanced_shading) {
|
||||
|
||||
/* loop over passes */
|
||||
BL::RenderLayer::passes_iterator b_pass_iter;
|
||||
|
||||
|
||||
for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
|
||||
BL::RenderPass b_pass(*b_pass_iter);
|
||||
PassType pass_type = get_pass_type(b_pass);
|
||||
@@ -217,13 +281,16 @@ void BlenderSession::render()
|
||||
}
|
||||
}
|
||||
|
||||
/* free result without merging */
|
||||
end_render_result(b_engine, b_rr, true);
|
||||
|
||||
buffer_params.passes = passes;
|
||||
scene->film->tag_passes_update(scene, passes);
|
||||
scene->film->tag_update(scene);
|
||||
scene->integrator->tag_update(scene);
|
||||
|
||||
/* update scene */
|
||||
sync->sync_data(b_v3d, b_engine.camera_override(), b_iter->name().c_str());
|
||||
sync->sync_data(b_v3d, b_engine.camera_override(), b_rlay_name.c_str());
|
||||
|
||||
/* update session */
|
||||
int samples = sync->get_layer_samples();
|
||||
@@ -235,19 +302,16 @@ void BlenderSession::render()
|
||||
|
||||
if(session->progress.get_cancel())
|
||||
break;
|
||||
|
||||
/* write result */
|
||||
write_render_result();
|
||||
}
|
||||
|
||||
/* delete render result */
|
||||
RE_engine_end_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
|
||||
/* clear callback */
|
||||
session->write_render_tile_cb = NULL;
|
||||
session->update_render_tile_cb = NULL;
|
||||
}
|
||||
|
||||
void BlenderSession::write_render_result()
|
||||
void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only)
|
||||
{
|
||||
/* get state */
|
||||
RenderBuffers *buffers = session->buffers;
|
||||
RenderBuffers *buffers = rtile.buffers;
|
||||
|
||||
/* copy data from device */
|
||||
if(!buffers->copy_from_device())
|
||||
@@ -255,41 +319,49 @@ void BlenderSession::write_render_result()
|
||||
|
||||
BufferParams& params = buffers->params;
|
||||
float exposure = scene->film->exposure;
|
||||
double total_time, sample_time;
|
||||
int sample;
|
||||
|
||||
session->progress.get_sample(sample, total_time, sample_time);
|
||||
|
||||
vector<float> pixels(params.width*params.height*4);
|
||||
|
||||
/* copy each pass */
|
||||
BL::RenderLayer::passes_iterator b_iter;
|
||||
|
||||
for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
|
||||
BL::RenderPass b_pass(*b_iter);
|
||||
if (!do_update_only) {
|
||||
/* copy each pass */
|
||||
BL::RenderLayer::passes_iterator b_iter;
|
||||
|
||||
/* find matching pass type */
|
||||
PassType pass_type = get_pass_type(b_pass);
|
||||
int components = b_pass.channels();
|
||||
for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
|
||||
BL::RenderPass b_pass(*b_iter);
|
||||
|
||||
/* copy pixels */
|
||||
if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0]))
|
||||
rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]);
|
||||
/* find matching pass type */
|
||||
PassType pass_type = get_pass_type(b_pass);
|
||||
int components = b_pass.channels();
|
||||
|
||||
/* copy pixels */
|
||||
if(buffers->get_pass_rect(pass_type, exposure, rtile.sample, components, &pixels[0]))
|
||||
rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* copy combined pass */
|
||||
if(buffers->get_pass(PASS_COMBINED, exposure, sample, 4, &pixels[0]))
|
||||
if(buffers->get_pass_rect(PASS_COMBINED, exposure, rtile.sample, 4, &pixels[0]))
|
||||
rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]);
|
||||
|
||||
/* tag result as updated */
|
||||
RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
|
||||
}
|
||||
|
||||
void BlenderSession::write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile)
|
||||
{
|
||||
do_write_update_render_result(b_rr, b_rlay, rtile, false);
|
||||
}
|
||||
|
||||
void BlenderSession::update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile)
|
||||
{
|
||||
do_write_update_render_result(b_rr, b_rlay, rtile, true);
|
||||
}
|
||||
|
||||
void BlenderSession::synchronize()
|
||||
{
|
||||
/* on session/scene parameter changes, we recreate session entirely */
|
||||
SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background);
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
|
||||
|
||||
if(session->params.modified(session_params) ||
|
||||
scene->params.modified(scene_params))
|
||||
@@ -300,6 +372,12 @@ void BlenderSession::synchronize()
|
||||
return;
|
||||
}
|
||||
|
||||
/* if the session is still resetting the device come back later */
|
||||
if(session->resetting()) {
|
||||
tag_update();
|
||||
return;
|
||||
}
|
||||
|
||||
/* increase samples, but never decrease */
|
||||
session->set_samples(session_params.samples);
|
||||
session->set_pause(BlenderSync::get_session_pause(b_scene, background));
|
||||
@@ -364,7 +442,7 @@ bool BlenderSession::draw(int w, int h)
|
||||
|
||||
/* reset if requested */
|
||||
if(reset) {
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
|
||||
SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background);
|
||||
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, scene->camera, w, h);
|
||||
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
@@ -387,11 +465,16 @@ void BlenderSession::get_status(string& status, string& substatus)
|
||||
|
||||
void BlenderSession::get_progress(float& progress, double& total_time)
|
||||
{
|
||||
double sample_time;
|
||||
int sample;
|
||||
double tile_time;
|
||||
int tile, sample, samples_per_tile;
|
||||
int tile_total = session->tile_manager.state.num_tiles;
|
||||
|
||||
session->progress.get_sample(sample, total_time, sample_time);
|
||||
progress = ((float)sample/(float)session->params.samples);
|
||||
session->progress.get_tile(tile, total_time, tile_time);
|
||||
|
||||
sample = session->progress.get_sample();
|
||||
samples_per_tile = session->tile_manager.state.num_samples;
|
||||
|
||||
progress = ((float)sample/(float)(tile_total * samples_per_tile));
|
||||
}
|
||||
|
||||
void BlenderSession::update_status_progress()
|
||||
@@ -404,8 +487,13 @@ void BlenderSession::update_status_progress()
|
||||
get_status(status, substatus);
|
||||
get_progress(progress, total_time);
|
||||
|
||||
timestatus = b_scene.name();
|
||||
if(b_rlay_name != "")
|
||||
timestatus += ", " + b_rlay_name;
|
||||
timestatus += " | ";
|
||||
|
||||
BLI_timestr(total_time, time_str);
|
||||
timestatus = "Elapsed: " + string(time_str) + " | ";
|
||||
timestatus += "Elapsed: " + string(time_str) + " | ";
|
||||
|
||||
if(substatus.size() > 0)
|
||||
status += " | " + substatus;
|
||||
@@ -435,7 +523,6 @@ void BlenderSession::tag_redraw()
|
||||
|
||||
/* offline render, redraw if timeout passed */
|
||||
if(time_dt() - last_redraw_time > 1.0) {
|
||||
write_render_result();
|
||||
engine_tag_redraw((RenderEngine*)b_engine.ptr.data);
|
||||
last_redraw_time = time_dt();
|
||||
}
|
||||
|
@@ -29,6 +29,8 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Scene;
|
||||
class Session;
|
||||
class RenderBuffers;
|
||||
class RenderTile;
|
||||
|
||||
class BlenderSession {
|
||||
public:
|
||||
@@ -46,7 +48,14 @@ public:
|
||||
|
||||
/* offline render */
|
||||
void render();
|
||||
void write_render_result();
|
||||
|
||||
void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
|
||||
void write_render_tile(RenderTile& rtile);
|
||||
|
||||
/* update functions are used to update display buffer only after sample was rendered
|
||||
* only needed for better visual feedback */
|
||||
void update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile);
|
||||
void update_render_tile(RenderTile& rtile);
|
||||
|
||||
/* interactive updates */
|
||||
void synchronize();
|
||||
@@ -72,13 +81,16 @@ public:
|
||||
BL::Scene b_scene;
|
||||
BL::SpaceView3D b_v3d;
|
||||
BL::RegionView3D b_rv3d;
|
||||
BL::RenderResult b_rr;
|
||||
BL::RenderLayer b_rlay;
|
||||
string b_rlay_name;
|
||||
|
||||
string last_status;
|
||||
float last_progress;
|
||||
|
||||
int width, height;
|
||||
|
||||
protected:
|
||||
void do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only);
|
||||
void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -221,6 +221,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
|
||||
BL::ShaderNodeMixRGB b_mix_node(b_node);
|
||||
MixNode *mix = new MixNode();
|
||||
mix->type = MixNode::type_enum[b_mix_node.blend_type()];
|
||||
mix->use_clamp = b_mix_node.use_clamp();
|
||||
node = mix;
|
||||
break;
|
||||
}
|
||||
@@ -244,6 +245,7 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
|
||||
BL::ShaderNodeMath b_math_node(b_node);
|
||||
MathNode *math = new MathNode();
|
||||
math->type = MathNode::type_enum[b_math_node.operation()];
|
||||
math->use_clamp = b_math_node.use_clamp();
|
||||
node = math;
|
||||
break;
|
||||
}
|
||||
@@ -404,6 +406,8 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
|
||||
if(b_image)
|
||||
image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
|
||||
image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
|
||||
image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
|
||||
image->projection_blend = b_image_node.projection_blend();
|
||||
get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
|
||||
node = image;
|
||||
break;
|
||||
@@ -459,6 +463,17 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
|
||||
node = checker;
|
||||
break;
|
||||
}
|
||||
case BL::ShaderNode::type_TEX_BRICK: {
|
||||
BL::ShaderNodeTexBrick b_brick_node(b_node);
|
||||
BrickTextureNode *brick = new BrickTextureNode();
|
||||
brick->offset = b_brick_node.offset();
|
||||
brick->offset_frequency = b_brick_node.offset_frequency();
|
||||
brick->squash = b_brick_node.squash();
|
||||
brick->squash_frequency = b_brick_node.squash_frequency();
|
||||
get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
|
||||
node = brick;
|
||||
break;
|
||||
}
|
||||
case BL::ShaderNode::type_TEX_NOISE: {
|
||||
BL::ShaderNodeTexNoise b_noise_node(b_node);
|
||||
NoiseTextureNode *noise = new NoiseTextureNode();
|
||||
|
@@ -40,15 +40,18 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Constructor */
|
||||
|
||||
BlenderSync::BlenderSync(BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_)
|
||||
: b_data(b_data_), b_scene(b_scene_),
|
||||
BlenderSync::BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_, Progress &progress_)
|
||||
: b_engine(b_engine_),
|
||||
b_data(b_data_), b_scene(b_scene_),
|
||||
shader_map(&scene_->shaders),
|
||||
object_map(&scene_->objects),
|
||||
mesh_map(&scene_->meshes),
|
||||
light_map(&scene_->lights),
|
||||
particle_system_map(&scene_->particle_systems),
|
||||
world_map(NULL),
|
||||
world_recalc(false),
|
||||
experimental(false)
|
||||
experimental(false),
|
||||
progress(progress_)
|
||||
{
|
||||
scene = scene_;
|
||||
preview = preview_;
|
||||
@@ -95,6 +98,12 @@ bool BlenderSync::sync_recalc()
|
||||
if(b_ob->is_updated_data() || b_ob->data().is_updated())
|
||||
light_map.set_recalc(*b_ob);
|
||||
}
|
||||
|
||||
if(b_ob->is_updated_data()) {
|
||||
BL::Object::particle_systems_iterator b_psys;
|
||||
for (b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys)
|
||||
particle_system_map.set_recalc(*b_ob);
|
||||
}
|
||||
}
|
||||
|
||||
BL::BlendData::meshes_iterator b_mesh;
|
||||
@@ -118,6 +127,7 @@ bool BlenderSync::sync_recalc()
|
||||
object_map.has_recalc() ||
|
||||
light_map.has_recalc() ||
|
||||
mesh_map.has_recalc() ||
|
||||
particle_system_map.has_recalc() ||
|
||||
BlendDataObjects_is_updated_get(&b_data.ptr) ||
|
||||
world_recalc;
|
||||
|
||||
@@ -131,6 +141,7 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, const
|
||||
sync_film();
|
||||
sync_shaders();
|
||||
sync_objects(b_v3d);
|
||||
sync_particle_systems();
|
||||
sync_motion(b_v3d, b_override);
|
||||
}
|
||||
|
||||
@@ -220,8 +231,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
|
||||
}
|
||||
else {
|
||||
render_layer.use_localview = (b_v3d.local_view() ? true : false);
|
||||
render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view());
|
||||
CYCLES_LOCAL_LAYER_HACK(render_layer.use_localview, render_layer.scene_layer);
|
||||
render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview);
|
||||
render_layer.layer = render_layer.scene_layer;
|
||||
render_layer.holdout_layer = 0;
|
||||
render_layer.material_override = PointerRNA_NULL;
|
||||
@@ -287,7 +297,7 @@ bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background)
|
||||
return (background)? false: get_boolean(cscene, "preview_pause");
|
||||
}
|
||||
|
||||
SessionParams BlenderSync::get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background)
|
||||
SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background)
|
||||
{
|
||||
SessionParams params;
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
@@ -341,25 +351,39 @@ SessionParams BlenderSync::get_session_params(BL::UserPreferences b_userpref, BL
|
||||
}
|
||||
}
|
||||
|
||||
/* tiles */
|
||||
if(params.device.type != DEVICE_CPU && !background) {
|
||||
/* currently GPU could be much slower than CPU when using tiles,
|
||||
* still need to be investigated, but meanwhile make it possible
|
||||
* to work in viewport smoothly
|
||||
*/
|
||||
int debug_tile_size = get_int(cscene, "debug_tile_size");
|
||||
|
||||
params.tile_size = make_int2(debug_tile_size, debug_tile_size);
|
||||
}
|
||||
else {
|
||||
int tile_x = b_engine.tile_x();
|
||||
int tile_y = b_engine.tile_y();
|
||||
|
||||
params.tile_size = make_int2(tile_x, tile_y);
|
||||
}
|
||||
|
||||
params.resolution = 1 << get_int(cscene, "resolution_divider");
|
||||
|
||||
/* other parameters */
|
||||
params.threads = b_scene.render().threads();
|
||||
params.tile_size = get_int(cscene, "debug_tile_size");
|
||||
params.min_size = get_int(cscene, "debug_min_size");
|
||||
|
||||
params.cancel_timeout = get_float(cscene, "debug_cancel_timeout");
|
||||
params.reset_timeout = get_float(cscene, "debug_reset_timeout");
|
||||
params.text_timeout = get_float(cscene, "debug_text_timeout");
|
||||
|
||||
if(background) {
|
||||
params.progressive = true;
|
||||
params.min_size = INT_MAX;
|
||||
params.progressive = false;
|
||||
params.resolution = 1;
|
||||
}
|
||||
else
|
||||
params.progressive = true;
|
||||
|
||||
/* todo: multi device only works with single tiles now */
|
||||
if(params.device.type == DEVICE_MULTI)
|
||||
params.tile_size = INT_MAX;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@@ -49,7 +49,7 @@ class ShaderNode;
|
||||
|
||||
class BlenderSync {
|
||||
public:
|
||||
BlenderSync(BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_);
|
||||
BlenderSync(BL::RenderEngine b_engine_, BL::BlendData b_data, BL::Scene b_scene, Scene *scene_, bool preview_, Progress &progress_);
|
||||
~BlenderSync();
|
||||
|
||||
/* sync */
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
/* get parameters */
|
||||
static SceneParams get_scene_params(BL::Scene b_scene, bool background);
|
||||
static SessionParams get_session_params(BL::UserPreferences b_userpref, BL::Scene b_scene, bool background);
|
||||
static SessionParams get_session_params(BL::RenderEngine b_engine, BL::UserPreferences b_userpref, BL::Scene b_scene, bool background);
|
||||
static bool get_session_pause(BL::Scene b_scene, bool background);
|
||||
static BufferParams get_buffer_params(BL::Scene b_scene, Camera *cam, int width, int height);
|
||||
|
||||
@@ -77,6 +77,7 @@ private:
|
||||
void sync_world();
|
||||
void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer);
|
||||
void sync_shaders();
|
||||
void sync_particle_systems();
|
||||
|
||||
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
|
||||
Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
|
||||
@@ -85,17 +86,18 @@ private:
|
||||
void sync_background_light();
|
||||
void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion);
|
||||
void sync_camera_motion(BL::Object b_ob, int motion);
|
||||
void sync_particles(Object *ob, BL::Object b_ob);
|
||||
void sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys);
|
||||
|
||||
/* util */
|
||||
void find_shader(BL::ID id, vector<uint>& used_shaders, int default_shader);
|
||||
bool BKE_object_is_modified(BL::Object b_ob);
|
||||
bool object_is_mesh(BL::Object b_ob);
|
||||
bool object_is_light(BL::Object b_ob);
|
||||
bool object_need_particle_update(BL::Object b_ob);
|
||||
bool psys_need_update(BL::ParticleSystem b_psys);
|
||||
int object_count_particles(BL::Object b_ob);
|
||||
|
||||
/* variables */
|
||||
BL::RenderEngine b_engine;
|
||||
BL::BlendData b_data;
|
||||
BL::Scene b_scene;
|
||||
|
||||
@@ -103,6 +105,7 @@ private:
|
||||
id_map<ObjectKey, Object> object_map;
|
||||
id_map<void*, Mesh> mesh_map;
|
||||
id_map<ObjectKey, Light> light_map;
|
||||
id_map<ParticleSystemKey, ParticleSystem> particle_system_map;
|
||||
set<Mesh*> mesh_synced;
|
||||
void *world_map;
|
||||
bool world_recalc;
|
||||
@@ -130,21 +133,9 @@ private:
|
||||
bool use_localview;
|
||||
int samples;
|
||||
} render_layer;
|
||||
};
|
||||
|
||||
/* we don't have spare bits for localview (normally 20-28)
|
||||
* because PATH_RAY_LAYER_SHIFT uses 20-32.
|
||||
* So - check if we have localview and if so, shift local
|
||||
* view bits down to 1-8, since this is done for the view
|
||||
* port only - it should be OK and not conflict with
|
||||
* render layers. - Campbell.
|
||||
*
|
||||
* ... as an alternative we could use uint64_t
|
||||
*/
|
||||
#define CYCLES_LOCAL_LAYER_HACK(use_localview, layer) \
|
||||
if (use_localview) { \
|
||||
layer >>= 20; \
|
||||
} (void)0
|
||||
Progress &progress;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@@ -40,9 +40,9 @@ void rna_Object_create_duplilist(void *ob, void *reports, void *sce);
|
||||
void rna_Object_free_duplilist(void *ob, void *reports);
|
||||
void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
|
||||
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
|
||||
struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h);
|
||||
struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h, const char *layername);
|
||||
void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result);
|
||||
void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result);
|
||||
void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result, int cancel);
|
||||
int RE_engine_test_break(struct RenderEngine *engine);
|
||||
void RE_engine_update_stats(struct RenderEngine *engine, const char *stats, const char *info);
|
||||
void RE_engine_update_progress(struct RenderEngine *engine, float progress);
|
||||
@@ -55,7 +55,6 @@ void rna_ColorRamp_eval(void *coba, float position, float color[4]);
|
||||
void rna_Scene_frame_set(void *scene, int frame, float subframe);
|
||||
void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
|
||||
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
|
||||
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -150,6 +149,11 @@ static inline float3 get_float3(BL::Array<float, 4> array)
|
||||
return make_float3(array[0], array[1], array[2]);
|
||||
}
|
||||
|
||||
static inline float4 get_float4(BL::Array<float, 4> array)
|
||||
{
|
||||
return make_float4(array[0], array[1], array[2], array[3]);
|
||||
}
|
||||
|
||||
static inline int4 get_int4(BL::Array<int, 4> array)
|
||||
{
|
||||
return make_int4(array[0], array[1], array[2], array[3]);
|
||||
@@ -166,7 +170,7 @@ static inline uint get_layer(BL::Array<int, 20> array)
|
||||
return layer;
|
||||
}
|
||||
|
||||
static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_array, bool is_light = false)
|
||||
static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_array, bool use_local, bool is_light = false)
|
||||
{
|
||||
uint layer = 0;
|
||||
|
||||
@@ -184,7 +188,14 @@ static inline uint get_layer(BL::Array<int, 20> array, BL::Array<int, 8> local_a
|
||||
if(local_array[i])
|
||||
layer |= (1 << (20+i));
|
||||
}
|
||||
|
||||
|
||||
/* we don't have spare bits for localview (normally 20-28) because
|
||||
* PATH_RAY_LAYER_SHIFT uses 20-32. So - check if we have localview and if
|
||||
* so, shift local view bits down to 1-8, since this is done for the view
|
||||
* port only - it should be OK and not conflict with render layers. */
|
||||
if(use_local)
|
||||
layer >>= 20;
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
@@ -389,6 +400,17 @@ struct ObjectKey {
|
||||
{ return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); }
|
||||
};
|
||||
|
||||
struct ParticleSystemKey {
|
||||
void *ob;
|
||||
void *psys;
|
||||
|
||||
ParticleSystemKey(void *ob_, void *psys_)
|
||||
: ob(ob_), psys(psys_) {}
|
||||
|
||||
bool operator<(const ParticleSystemKey& k) const
|
||||
{ return (ob < k.ob && psys < k.psys); }
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BLENDER_UTIL_H__ */
|
||||
|
@@ -17,32 +17,6 @@ else()
|
||||
set(CYCLES_GLEW_LIBRARY extern_glew)
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# OpenShadingLanguage
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
|
||||
set(CYCLES_OSL "" CACHE PATH "Path to OpenShadingLanguage installation")
|
||||
|
||||
message(STATUS "CYCLES_OSL = ${CYCLES_OSL}")
|
||||
|
||||
find_library(OSL_LIBRARIES NAMES oslexec oslcomp oslquery PATHS ${CYCLES_OSL}/lib ${CYCLES_OSL}/dist)
|
||||
find_path(OSL_INCLUDES OSL/oslclosure.h PATHS ${CYCLES_OSL}/include ${CYCLES_OSL}/dist)
|
||||
find_program(OSL_COMPILER NAMES oslc PATHS ${CYCLES_OSL}/bin ${CYCLES_OSL}/dist)
|
||||
|
||||
if(OSL_INCLUDES AND OSL_LIBRARIES AND OSL_COMPILER)
|
||||
set(OSL_FOUND TRUE)
|
||||
message(STATUS "OSL includes = ${OSL_INCLUDES}")
|
||||
message(STATUS "OSL library = ${OSL_LIBRARIES}")
|
||||
message(STATUS "OSL compiler = ${OSL_COMPILER}")
|
||||
else()
|
||||
message(STATUS "OSL not found")
|
||||
endif()
|
||||
|
||||
include_directories(${OSL_INCLUDES} ${OSL_INCLUDES}/OSL ${OSL_INCLUDES}/../../../src/liboslexec)
|
||||
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# Partio
|
||||
|
||||
|
@@ -17,6 +17,7 @@ set(SRC
|
||||
device_multi.cpp
|
||||
device_network.cpp
|
||||
device_opencl.cpp
|
||||
device_task.cpp
|
||||
)
|
||||
|
||||
set(SRC_HEADERS
|
||||
@@ -24,6 +25,7 @@ set(SRC_HEADERS
|
||||
device_memory.h
|
||||
device_intern.h
|
||||
device_network.h
|
||||
device_task.h
|
||||
)
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
|
@@ -33,65 +33,6 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Device Task */
|
||||
|
||||
DeviceTask::DeviceTask(Type type_)
|
||||
: type(type_), x(0), y(0), w(0), h(0), rng_state(0), rgba(0), buffer(0),
|
||||
sample(0), resolution(0),
|
||||
shader_input(0), shader_output(0),
|
||||
shader_eval_type(0), shader_x(0), shader_w(0)
|
||||
{
|
||||
}
|
||||
|
||||
void DeviceTask::split_max_size(list<DeviceTask>& tasks, int max_size)
|
||||
{
|
||||
int num;
|
||||
|
||||
if(type == SHADER) {
|
||||
num = (shader_w + max_size - 1)/max_size;
|
||||
}
|
||||
else {
|
||||
max_size = max(1, max_size/w);
|
||||
num = (h + max_size - 1)/max_size;
|
||||
}
|
||||
|
||||
split(tasks, num);
|
||||
}
|
||||
|
||||
void DeviceTask::split(list<DeviceTask>& tasks, int num)
|
||||
{
|
||||
if(type == SHADER) {
|
||||
num = min(shader_w, num);
|
||||
|
||||
for(int i = 0; i < num; i++) {
|
||||
int tx = shader_x + (shader_w/num)*i;
|
||||
int tw = (i == num-1)? shader_w - i*(shader_w/num): shader_w/num;
|
||||
|
||||
DeviceTask task = *this;
|
||||
|
||||
task.shader_x = tx;
|
||||
task.shader_w = tw;
|
||||
|
||||
tasks.push_back(task);
|
||||
}
|
||||
}
|
||||
else {
|
||||
num = min(h, num);
|
||||
|
||||
for(int i = 0; i < num; i++) {
|
||||
int ty = y + (h/num)*i;
|
||||
int th = (i == num-1)? h - i*(h/num): h/num;
|
||||
|
||||
DeviceTask task = *this;
|
||||
|
||||
task.y = ty;
|
||||
task.h = th;
|
||||
|
||||
tasks.push_back(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Device */
|
||||
|
||||
void Device::pixels_alloc(device_memory& mem)
|
||||
|
@@ -22,10 +22,10 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "device_memory.h"
|
||||
#include "device_task.h"
|
||||
|
||||
#include "util_list.h"
|
||||
#include "util_string.h"
|
||||
#include "util_task.h"
|
||||
#include "util_thread.h"
|
||||
#include "util_types.h"
|
||||
#include "util_vector.h"
|
||||
@@ -33,6 +33,7 @@
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Progress;
|
||||
class RenderTile;
|
||||
|
||||
/* Device Types */
|
||||
|
||||
@@ -67,32 +68,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/* Device Task */
|
||||
|
||||
class DeviceTask : public Task {
|
||||
public:
|
||||
typedef enum { PATH_TRACE, TONEMAP, SHADER } Type;
|
||||
Type type;
|
||||
|
||||
int x, y, w, h;
|
||||
device_ptr rng_state;
|
||||
device_ptr rgba;
|
||||
device_ptr buffer;
|
||||
int sample;
|
||||
int resolution;
|
||||
int offset, stride;
|
||||
|
||||
device_ptr shader_input;
|
||||
device_ptr shader_output;
|
||||
int shader_eval_type;
|
||||
int shader_x, shader_w;
|
||||
|
||||
DeviceTask(Type type = PATH_TRACE);
|
||||
|
||||
void split(list<DeviceTask>& tasks, int num);
|
||||
void split_max_size(list<DeviceTask>& tasks, int max_size);
|
||||
};
|
||||
|
||||
/* Device */
|
||||
|
||||
class Device {
|
||||
@@ -140,6 +115,7 @@ public:
|
||||
virtual void task_add(DeviceTask& task) = 0;
|
||||
virtual void task_wait() = 0;
|
||||
virtual void task_cancel() = 0;
|
||||
virtual bool task_cancelled() = 0;
|
||||
|
||||
/* opengl drawing */
|
||||
virtual void draw_pixels(device_memory& mem, int y, int w, int h,
|
||||
@@ -150,6 +126,10 @@ public:
|
||||
void server_run();
|
||||
#endif
|
||||
|
||||
/* multi device */
|
||||
virtual void map_tile(Device *sub_device, RenderTile& tile) {}
|
||||
virtual int device_number(Device *sub_device) { return 0; }
|
||||
|
||||
/* static */
|
||||
static Device *create(DeviceInfo& info, bool background = true, int threads = 0);
|
||||
|
||||
|
@@ -27,6 +27,8 @@
|
||||
|
||||
#include "osl_shader.h"
|
||||
|
||||
#include "buffers.h"
|
||||
|
||||
#include "util_debug.h"
|
||||
#include "util_foreach.h"
|
||||
#include "util_function.h"
|
||||
@@ -141,28 +143,56 @@ public:
|
||||
OSLShader::thread_init(kg);
|
||||
#endif
|
||||
|
||||
RenderTile tile;
|
||||
|
||||
while(task.acquire_tile(this, tile)) {
|
||||
float *render_buffer = (float*)tile.buffer;
|
||||
uint *rng_state = (uint*)tile.rng_state;
|
||||
int start_sample = tile.start_sample;
|
||||
int end_sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
#ifdef WITH_OPTIMIZED_KERNEL
|
||||
if(system_cpu_support_optimized()) {
|
||||
for(int y = task.y; y < task.y + task.h; y++) {
|
||||
for(int x = task.x; x < task.x + task.w; x++)
|
||||
kernel_cpu_optimized_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
|
||||
task.sample, x, y, task.offset, task.stride);
|
||||
if(system_cpu_support_optimized()) {
|
||||
for(int sample = start_sample; sample < end_sample; sample++) {
|
||||
if (task.get_cancel() || task_pool.cancelled())
|
||||
break;
|
||||
|
||||
if(task_pool.cancelled())
|
||||
break;
|
||||
for(int y = tile.y; y < tile.y + tile.h; y++) {
|
||||
for(int x = tile.x; x < tile.x + tile.w; x++) {
|
||||
kernel_cpu_optimized_path_trace(kg, render_buffer, rng_state,
|
||||
sample, x, y, tile.offset, tile.stride);
|
||||
}
|
||||
}
|
||||
|
||||
tile.sample = sample + 1;
|
||||
|
||||
task.update_progress(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for(int y = task.y; y < task.y + task.h; y++) {
|
||||
for(int x = task.x; x < task.x + task.w; x++)
|
||||
kernel_cpu_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
|
||||
task.sample, x, y, task.offset, task.stride);
|
||||
{
|
||||
for(int sample = start_sample; sample < end_sample; sample++) {
|
||||
if (task.get_cancel() || task_pool.cancelled())
|
||||
break;
|
||||
|
||||
if(task_pool.cancelled())
|
||||
break;
|
||||
for(int y = tile.y; y < tile.y + tile.h; y++) {
|
||||
for(int x = tile.x; x < tile.x + tile.w; x++) {
|
||||
kernel_cpu_path_trace(kg, render_buffer, rng_state,
|
||||
sample, x, y, tile.offset, tile.stride);
|
||||
}
|
||||
}
|
||||
|
||||
tile.sample = sample + 1;
|
||||
|
||||
task.update_progress(tile);
|
||||
}
|
||||
}
|
||||
|
||||
task.release_tile(tile);
|
||||
|
||||
if(task_pool.cancelled())
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef WITH_OSL
|
||||
@@ -228,8 +258,7 @@ public:
|
||||
/* split task into smaller ones, more than number of threads for uneven
|
||||
* workloads where some parts of the image render slower than others */
|
||||
list<DeviceTask> tasks;
|
||||
|
||||
task.split(tasks, TaskScheduler::num_threads()*10);
|
||||
task.split(tasks, TaskScheduler::num_threads()+1);
|
||||
|
||||
foreach(DeviceTask& task, tasks)
|
||||
task_pool.push(new CPUDeviceTask(this, task));
|
||||
@@ -244,6 +273,11 @@ public:
|
||||
{
|
||||
task_pool.cancel();
|
||||
}
|
||||
|
||||
bool task_cancelled()
|
||||
{
|
||||
return task_pool.cancelled();
|
||||
}
|
||||
};
|
||||
|
||||
Device *device_cpu_create(DeviceInfo& info, int threads)
|
||||
|
@@ -23,6 +23,8 @@
|
||||
#include "device.h"
|
||||
#include "device_intern.h"
|
||||
|
||||
#include "buffers.h"
|
||||
|
||||
#include "util_cuda.h"
|
||||
#include "util_debug.h"
|
||||
#include "util_map.h"
|
||||
@@ -37,6 +39,7 @@ CCL_NAMESPACE_BEGIN
|
||||
class CUDADevice : public Device
|
||||
{
|
||||
public:
|
||||
TaskPool task_pool;
|
||||
CUdevice cuDevice;
|
||||
CUcontext cuContext;
|
||||
CUmodule cuModule;
|
||||
@@ -192,6 +195,8 @@ public:
|
||||
|
||||
~CUDADevice()
|
||||
{
|
||||
task_pool.stop();
|
||||
|
||||
cuda_push_context();
|
||||
cuda_assert(cuCtxDetach(cuContext))
|
||||
}
|
||||
@@ -466,13 +471,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void path_trace(DeviceTask& task)
|
||||
void path_trace(RenderTile& rtile, int sample)
|
||||
{
|
||||
cuda_push_context();
|
||||
|
||||
CUfunction cuPathTrace;
|
||||
CUdeviceptr d_buffer = cuda_device_ptr(task.buffer);
|
||||
CUdeviceptr d_rng_state = cuda_device_ptr(task.rng_state);
|
||||
CUdeviceptr d_buffer = cuda_device_ptr(rtile.buffer);
|
||||
CUdeviceptr d_rng_state = cuda_device_ptr(rtile.rng_state);
|
||||
|
||||
/* get kernel function */
|
||||
cuda_assert(cuModuleGetFunction(&cuPathTrace, cuModule, "kernel_cuda_path_trace"))
|
||||
@@ -486,29 +491,28 @@ public:
|
||||
cuda_assert(cuParamSetv(cuPathTrace, offset, &d_rng_state, sizeof(d_rng_state)))
|
||||
offset += sizeof(d_rng_state);
|
||||
|
||||
int sample = task.sample;
|
||||
offset = align_up(offset, __alignof(sample));
|
||||
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, task.sample))
|
||||
offset += sizeof(task.sample);
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, sample))
|
||||
offset += sizeof(sample);
|
||||
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, task.x))
|
||||
offset += sizeof(task.x);
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.x))
|
||||
offset += sizeof(rtile.x);
|
||||
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, task.y))
|
||||
offset += sizeof(task.y);
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.y))
|
||||
offset += sizeof(rtile.y);
|
||||
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, task.w))
|
||||
offset += sizeof(task.w);
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.w))
|
||||
offset += sizeof(rtile.w);
|
||||
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, task.h))
|
||||
offset += sizeof(task.h);
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.h))
|
||||
offset += sizeof(rtile.h);
|
||||
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, task.offset))
|
||||
offset += sizeof(task.offset);
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.offset))
|
||||
offset += sizeof(rtile.offset);
|
||||
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, task.stride))
|
||||
offset += sizeof(task.stride);
|
||||
cuda_assert(cuParamSeti(cuPathTrace, offset, rtile.stride))
|
||||
offset += sizeof(rtile.stride);
|
||||
|
||||
cuda_assert(cuParamSetSize(cuPathTrace, offset))
|
||||
|
||||
@@ -520,23 +524,25 @@ public:
|
||||
int xthreads = 8;
|
||||
int ythreads = 8;
|
||||
#endif
|
||||
int xblocks = (task.w + xthreads - 1)/xthreads;
|
||||
int yblocks = (task.h + ythreads - 1)/ythreads;
|
||||
int xblocks = (rtile.w + xthreads - 1)/xthreads;
|
||||
int yblocks = (rtile.h + ythreads - 1)/ythreads;
|
||||
|
||||
cuda_assert(cuFuncSetCacheConfig(cuPathTrace, CU_FUNC_CACHE_PREFER_L1))
|
||||
cuda_assert(cuFuncSetBlockShape(cuPathTrace, xthreads, ythreads, 1))
|
||||
cuda_assert(cuLaunchGrid(cuPathTrace, xblocks, yblocks))
|
||||
|
||||
cuda_assert(cuCtxSynchronize())
|
||||
|
||||
cuda_pop_context();
|
||||
}
|
||||
|
||||
void tonemap(DeviceTask& task)
|
||||
void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
|
||||
{
|
||||
cuda_push_context();
|
||||
|
||||
CUfunction cuFilmConvert;
|
||||
CUdeviceptr d_rgba = map_pixels(task.rgba);
|
||||
CUdeviceptr d_buffer = cuda_device_ptr(task.buffer);
|
||||
CUdeviceptr d_rgba = map_pixels(rgba);
|
||||
CUdeviceptr d_buffer = cuda_device_ptr(buffer);
|
||||
|
||||
/* get kernel function */
|
||||
cuda_assert(cuModuleGetFunction(&cuFilmConvert, cuModule, "kernel_cuda_tonemap"))
|
||||
@@ -820,27 +826,76 @@ public:
|
||||
Device::draw_pixels(mem, y, w, h, dy, width, height, transparent);
|
||||
}
|
||||
|
||||
void thread_run(DeviceTask *task)
|
||||
{
|
||||
if(task->type == DeviceTask::PATH_TRACE) {
|
||||
RenderTile tile;
|
||||
|
||||
/* keep rendering tiles until done */
|
||||
while(task->acquire_tile(this, tile)) {
|
||||
int start_sample = tile.start_sample;
|
||||
int end_sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
for(int sample = start_sample; sample < end_sample; sample++) {
|
||||
if (task->get_cancel())
|
||||
break;
|
||||
|
||||
path_trace(tile, sample);
|
||||
|
||||
tile.sample = sample + 1;
|
||||
|
||||
task->update_progress(tile);
|
||||
}
|
||||
|
||||
task->release_tile(tile);
|
||||
}
|
||||
}
|
||||
else if(task->type == DeviceTask::SHADER) {
|
||||
shader(*task);
|
||||
|
||||
cuda_push_context();
|
||||
cuda_assert(cuCtxSynchronize())
|
||||
cuda_pop_context();
|
||||
}
|
||||
}
|
||||
|
||||
class CUDADeviceTask : public DeviceTask {
|
||||
public:
|
||||
CUDADeviceTask(CUDADevice *device, DeviceTask& task)
|
||||
: DeviceTask(task)
|
||||
{
|
||||
run = function_bind(&CUDADevice::thread_run, device, this);
|
||||
}
|
||||
};
|
||||
|
||||
void task_add(DeviceTask& task)
|
||||
{
|
||||
if(task.type == DeviceTask::TONEMAP)
|
||||
tonemap(task);
|
||||
else if(task.type == DeviceTask::PATH_TRACE)
|
||||
path_trace(task);
|
||||
else if(task.type == DeviceTask::SHADER)
|
||||
shader(task);
|
||||
if(task.type == DeviceTask::TONEMAP) {
|
||||
/* must be done in main thread due to opengl access */
|
||||
tonemap(task, task.buffer, task.rgba);
|
||||
|
||||
cuda_push_context();
|
||||
cuda_assert(cuCtxSynchronize())
|
||||
cuda_pop_context();
|
||||
}
|
||||
else {
|
||||
task_pool.push(new CUDADeviceTask(this, task));
|
||||
}
|
||||
}
|
||||
|
||||
void task_wait()
|
||||
{
|
||||
cuda_push_context();
|
||||
|
||||
cuda_assert(cuCtxSynchronize())
|
||||
|
||||
cuda_pop_context();
|
||||
task_pool.wait_work();
|
||||
}
|
||||
|
||||
void task_cancel()
|
||||
{
|
||||
task_pool.cancel();
|
||||
}
|
||||
|
||||
bool task_cancelled()
|
||||
{
|
||||
return task_pool.cancelled();
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -23,6 +23,8 @@
|
||||
#include "device_intern.h"
|
||||
#include "device_network.h"
|
||||
|
||||
#include "buffers.h"
|
||||
|
||||
#include "util_foreach.h"
|
||||
#include "util_list.h"
|
||||
#include "util_map.h"
|
||||
@@ -255,6 +257,30 @@ public:
|
||||
rgba.device_pointer = tmp;
|
||||
}
|
||||
|
||||
void map_tile(Device *sub_device, RenderTile& tile)
|
||||
{
|
||||
foreach(SubDevice& sub, devices) {
|
||||
if(sub.device == sub_device) {
|
||||
if(tile.buffer) tile.buffer = sub.ptr_map[tile.buffer];
|
||||
if(tile.rng_state) tile.rng_state = sub.ptr_map[tile.rng_state];
|
||||
if(tile.rgba) tile.rgba = sub.ptr_map[tile.rgba];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int device_number(Device *sub_device)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
foreach(SubDevice& sub, devices) {
|
||||
if(sub.device == sub_device)
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void task_add(DeviceTask& task)
|
||||
{
|
||||
list<DeviceTask> tasks;
|
||||
@@ -266,7 +292,6 @@ public:
|
||||
tasks.pop_front();
|
||||
|
||||
if(task.buffer) subtask.buffer = sub.ptr_map[task.buffer];
|
||||
if(task.rng_state) subtask.rng_state = sub.ptr_map[task.rng_state];
|
||||
if(task.rgba) subtask.rgba = sub.ptr_map[task.rgba];
|
||||
if(task.shader_input) subtask.shader_input = sub.ptr_map[task.shader_input];
|
||||
if(task.shader_output) subtask.shader_output = sub.ptr_map[task.shader_output];
|
||||
@@ -287,6 +312,14 @@ public:
|
||||
foreach(SubDevice& sub, devices)
|
||||
sub.device->task_cancel();
|
||||
}
|
||||
|
||||
bool task_cancelled()
|
||||
{
|
||||
foreach(SubDevice& sub, devices)
|
||||
if (sub.device->task_cancelled())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Device *device_multi_create(DeviceInfo& info, bool background)
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#include "device.h"
|
||||
#include "device_intern.h"
|
||||
|
||||
#include "buffers.h"
|
||||
|
||||
#include "util_foreach.h"
|
||||
#include "util_map.h"
|
||||
#include "util_math.h"
|
||||
@@ -41,6 +43,7 @@ CCL_NAMESPACE_BEGIN
|
||||
class OpenCLDevice : public Device
|
||||
{
|
||||
public:
|
||||
TaskPool task_pool;
|
||||
cl_context cxContext;
|
||||
cl_command_queue cqCommandQueue;
|
||||
cl_platform_id cpPlatform;
|
||||
@@ -435,6 +438,8 @@ public:
|
||||
|
||||
~OpenCLDevice()
|
||||
{
|
||||
task_pool.stop();
|
||||
|
||||
if(null_mem)
|
||||
clReleaseMemObject(CL_MEM_PTR(null_mem));
|
||||
|
||||
@@ -540,19 +545,19 @@ public:
|
||||
return global_size + ((r == 0)? 0: group_size - r);
|
||||
}
|
||||
|
||||
void path_trace(DeviceTask& task)
|
||||
void path_trace(RenderTile& rtile, int sample)
|
||||
{
|
||||
/* cast arguments to cl types */
|
||||
cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
|
||||
cl_mem d_buffer = CL_MEM_PTR(task.buffer);
|
||||
cl_mem d_rng_state = CL_MEM_PTR(task.rng_state);
|
||||
cl_int d_x = task.x;
|
||||
cl_int d_y = task.y;
|
||||
cl_int d_w = task.w;
|
||||
cl_int d_h = task.h;
|
||||
cl_int d_sample = task.sample;
|
||||
cl_int d_offset = task.offset;
|
||||
cl_int d_stride = task.stride;
|
||||
cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
|
||||
cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state);
|
||||
cl_int d_x = rtile.x;
|
||||
cl_int d_y = rtile.y;
|
||||
cl_int d_w = rtile.w;
|
||||
cl_int d_h = rtile.h;
|
||||
cl_int d_sample = sample;
|
||||
cl_int d_offset = rtile.offset;
|
||||
cl_int d_stride = rtile.stride;
|
||||
|
||||
/* sample arguments */
|
||||
int narg = 0;
|
||||
@@ -613,12 +618,12 @@ public:
|
||||
return err;
|
||||
}
|
||||
|
||||
void tonemap(DeviceTask& task)
|
||||
void tonemap(DeviceTask& task, device_ptr buffer, device_ptr rgba)
|
||||
{
|
||||
/* cast arguments to cl types */
|
||||
cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
|
||||
cl_mem d_rgba = CL_MEM_PTR(task.rgba);
|
||||
cl_mem d_buffer = CL_MEM_PTR(task.buffer);
|
||||
cl_mem d_rgba = CL_MEM_PTR(rgba);
|
||||
cl_mem d_buffer = CL_MEM_PTR(buffer);
|
||||
cl_int d_x = task.x;
|
||||
cl_int d_y = task.y;
|
||||
cl_int d_w = task.w;
|
||||
@@ -667,30 +672,62 @@ public:
|
||||
opencl_assert(clFinish(cqCommandQueue));
|
||||
}
|
||||
|
||||
void task_add(DeviceTask& maintask)
|
||||
void thread_run(DeviceTask *task)
|
||||
{
|
||||
list<DeviceTask> tasks;
|
||||
|
||||
/* arbitrary limit to work around apple ATI opencl issue */
|
||||
if(platform_name == "Apple")
|
||||
maintask.split_max_size(tasks, 76800);
|
||||
else
|
||||
tasks.push_back(maintask);
|
||||
|
||||
foreach(DeviceTask& task, tasks) {
|
||||
if(task.type == DeviceTask::TONEMAP)
|
||||
tonemap(task);
|
||||
else if(task.type == DeviceTask::PATH_TRACE)
|
||||
path_trace(task);
|
||||
if(task->type == DeviceTask::TONEMAP) {
|
||||
tonemap(*task, task->buffer, task->rgba);
|
||||
}
|
||||
else if(task->type == DeviceTask::PATH_TRACE) {
|
||||
RenderTile tile;
|
||||
|
||||
/* keep rendering tiles until done */
|
||||
while(task->acquire_tile(this, tile)) {
|
||||
int start_sample = tile.start_sample;
|
||||
int end_sample = tile.start_sample + tile.num_samples;
|
||||
|
||||
for(int sample = start_sample; sample < end_sample; sample++) {
|
||||
if (task->get_cancel())
|
||||
break;
|
||||
|
||||
path_trace(tile, sample);
|
||||
|
||||
tile.sample = sample + 1;
|
||||
|
||||
task->update_progress(tile);
|
||||
}
|
||||
|
||||
task->release_tile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class OpenCLDeviceTask : public DeviceTask {
|
||||
public:
|
||||
OpenCLDeviceTask(OpenCLDevice *device, DeviceTask& task)
|
||||
: DeviceTask(task)
|
||||
{
|
||||
run = function_bind(&OpenCLDevice::thread_run, device, this);
|
||||
}
|
||||
};
|
||||
|
||||
void task_add(DeviceTask& task)
|
||||
{
|
||||
task_pool.push(new OpenCLDeviceTask(this, task));
|
||||
}
|
||||
|
||||
void task_wait()
|
||||
{
|
||||
task_pool.wait_work();
|
||||
}
|
||||
|
||||
void task_cancel()
|
||||
{
|
||||
task_pool.cancel();
|
||||
}
|
||||
|
||||
bool task_cancelled()
|
||||
{
|
||||
return task_pool.cancelled();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -702,29 +739,31 @@ Device *device_opencl_create(DeviceInfo& info, bool background)
|
||||
void device_opencl_info(vector<DeviceInfo>& devices)
|
||||
{
|
||||
vector<cl_device_id> device_ids;
|
||||
cl_uint num_devices;
|
||||
cl_platform_id platform_id;
|
||||
cl_uint num_platforms;
|
||||
cl_uint num_devices = 0;
|
||||
vector<cl_platform_id> platform_ids;
|
||||
cl_uint num_platforms = 0;
|
||||
|
||||
/* get devices */
|
||||
if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS || num_platforms == 0)
|
||||
return;
|
||||
|
||||
platform_ids.resize(num_platforms);
|
||||
|
||||
if(clGetPlatformIDs(1, &platform_id, NULL) != CL_SUCCESS)
|
||||
if(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL) != CL_SUCCESS)
|
||||
return;
|
||||
|
||||
if(clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, 0, NULL, &num_devices) != CL_SUCCESS)
|
||||
if(clGetDeviceIDs(platform_ids[0], CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, 0, NULL, &num_devices) != CL_SUCCESS || num_devices == 0)
|
||||
return;
|
||||
|
||||
device_ids.resize(num_devices);
|
||||
|
||||
if(clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, num_devices, &device_ids[0], NULL) != CL_SUCCESS)
|
||||
if(clGetDeviceIDs(platform_ids[0], CL_DEVICE_TYPE_GPU|CL_DEVICE_TYPE_ACCELERATOR, num_devices, &device_ids[0], NULL) != CL_SUCCESS)
|
||||
return;
|
||||
|
||||
/* add devices */
|
||||
for(int num = 0; num < num_devices; num++) {
|
||||
cl_device_id device_id = device_ids[num];
|
||||
char name[1024];
|
||||
char name[1024] = "\0";
|
||||
|
||||
if(clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(name), &name, NULL) != CL_SUCCESS)
|
||||
continue;
|
||||
|
113
intern/cycles/device/device_task.cpp
Normal file
113
intern/cycles/device/device_task.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "device_task.h"
|
||||
|
||||
#include "util_algorithm.h"
|
||||
#include "util_time.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Device Task */
|
||||
|
||||
DeviceTask::DeviceTask(Type type_)
|
||||
: type(type_), x(0), y(0), w(0), h(0), rgba(0), buffer(0),
|
||||
sample(0), num_samples(1), resolution(0),
|
||||
shader_input(0), shader_output(0),
|
||||
shader_eval_type(0), shader_x(0), shader_w(0)
|
||||
{
|
||||
last_update_time = time_dt();
|
||||
}
|
||||
|
||||
void DeviceTask::split_max_size(list<DeviceTask>& tasks, int max_size)
|
||||
{
|
||||
int num;
|
||||
|
||||
if(type == SHADER) {
|
||||
num = (shader_w + max_size - 1)/max_size;
|
||||
}
|
||||
else {
|
||||
max_size = max(1, max_size/w);
|
||||
num = (h + max_size - 1)/max_size;
|
||||
}
|
||||
|
||||
split(tasks, num);
|
||||
}
|
||||
|
||||
void DeviceTask::split(list<DeviceTask>& tasks, int num)
|
||||
{
|
||||
if(type == SHADER) {
|
||||
num = min(shader_w, num);
|
||||
|
||||
for(int i = 0; i < num; i++) {
|
||||
int tx = shader_x + (shader_w/num)*i;
|
||||
int tw = (i == num-1)? shader_w - i*(shader_w/num): shader_w/num;
|
||||
|
||||
DeviceTask task = *this;
|
||||
|
||||
task.shader_x = tx;
|
||||
task.shader_w = tw;
|
||||
|
||||
tasks.push_back(task);
|
||||
}
|
||||
}
|
||||
else if(type == PATH_TRACE) {
|
||||
for(int i = 0; i < num; i++)
|
||||
tasks.push_back(*this);
|
||||
}
|
||||
else {
|
||||
num = min(h, num);
|
||||
|
||||
for(int i = 0; i < num; i++) {
|
||||
int ty = y + (h/num)*i;
|
||||
int th = (i == num-1)? h - i*(h/num): h/num;
|
||||
|
||||
DeviceTask task = *this;
|
||||
|
||||
task.y = ty;
|
||||
task.h = th;
|
||||
|
||||
tasks.push_back(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceTask::update_progress(RenderTile &rtile)
|
||||
{
|
||||
if (type != PATH_TRACE)
|
||||
return;
|
||||
|
||||
if(update_progress_sample)
|
||||
update_progress_sample();
|
||||
|
||||
if(update_tile_sample) {
|
||||
double current_time = time_dt();
|
||||
|
||||
if (current_time - last_update_time >= 1.0f) {
|
||||
update_tile_sample(rtile);
|
||||
|
||||
last_update_time = current_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
75
intern/cycles/device/device_task.h
Normal file
75
intern/cycles/device/device_task.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_TASK_H__
|
||||
#define __DEVICE_TASK_H__
|
||||
|
||||
#include "device_memory.h"
|
||||
|
||||
#include "util_function.h"
|
||||
#include "util_list.h"
|
||||
#include "util_task.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Device Task */
|
||||
|
||||
class Device;
|
||||
class RenderBuffers;
|
||||
class RenderTile;
|
||||
class Tile;
|
||||
|
||||
class DeviceTask : public Task {
|
||||
public:
|
||||
typedef enum { PATH_TRACE, TONEMAP, SHADER } Type;
|
||||
Type type;
|
||||
|
||||
int x, y, w, h;
|
||||
device_ptr rgba;
|
||||
device_ptr buffer;
|
||||
int sample;
|
||||
int num_samples;
|
||||
int resolution;
|
||||
int offset, stride;
|
||||
|
||||
device_ptr shader_input;
|
||||
device_ptr shader_output;
|
||||
int shader_eval_type;
|
||||
int shader_x, shader_w;
|
||||
|
||||
DeviceTask(Type type = PATH_TRACE);
|
||||
|
||||
void split(list<DeviceTask>& tasks, int num);
|
||||
void split_max_size(list<DeviceTask>& tasks, int max_size);
|
||||
|
||||
void update_progress(RenderTile &rtile);
|
||||
|
||||
boost::function<bool(Device *device, RenderTile&)> acquire_tile;
|
||||
boost::function<void(void)> update_progress_sample;
|
||||
boost::function<void(RenderTile&)> update_tile_sample;
|
||||
boost::function<void(RenderTile&)> release_tile;
|
||||
boost::function<bool(void)> get_cancel;
|
||||
|
||||
protected:
|
||||
double last_update_time;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __DEVICE_TASK_H__ */
|
||||
|
@@ -16,6 +16,7 @@ set(SRC
|
||||
set(SRC_HEADERS
|
||||
kernel.h
|
||||
kernel_accumulate.h
|
||||
kernel_attribute.h
|
||||
kernel_bvh.h
|
||||
kernel_camera.h
|
||||
kernel_compat_cpu.h
|
||||
@@ -61,6 +62,7 @@ set(SRC_SVM_HEADERS
|
||||
svm/svm_closure.h
|
||||
svm/svm_convert.h
|
||||
svm/svm_checker.h
|
||||
svm/svm_brick.h
|
||||
svm/svm_displace.h
|
||||
svm/svm_fresnel.h
|
||||
svm/svm_gamma.h
|
||||
|
@@ -87,14 +87,10 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
|
||||
else if(strstr(name, "__tex_image_float")) {
|
||||
texture_image_float4 *tex = NULL;
|
||||
int id = atoi(name + strlen("__tex_image_float_"));
|
||||
int array_index = id;
|
||||
|
||||
switch(id) {
|
||||
case 95: tex = &kg->__tex_image_float_095; break;
|
||||
case 96: tex = &kg->__tex_image_float_096; break;
|
||||
case 97: tex = &kg->__tex_image_float_097; break;
|
||||
case 98: tex = &kg->__tex_image_float_098; break;
|
||||
case 99: tex = &kg->__tex_image_float_099; break;
|
||||
default: break;
|
||||
if (array_index >= 0 && array_index < MAX_FLOAT_IMAGES) {
|
||||
tex = &kg->texture_float_images[array_index];
|
||||
}
|
||||
|
||||
if(tex) {
|
||||
@@ -106,104 +102,10 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
|
||||
else if(strstr(name, "__tex_image")) {
|
||||
texture_image_uchar4 *tex = NULL;
|
||||
int id = atoi(name + strlen("__tex_image_"));
|
||||
int array_index = id - MAX_FLOAT_IMAGES;
|
||||
|
||||
switch(id) {
|
||||
case 0: tex = &kg->__tex_image_000; break;
|
||||
case 1: tex = &kg->__tex_image_001; break;
|
||||
case 2: tex = &kg->__tex_image_002; break;
|
||||
case 3: tex = &kg->__tex_image_003; break;
|
||||
case 4: tex = &kg->__tex_image_004; break;
|
||||
case 5: tex = &kg->__tex_image_005; break;
|
||||
case 6: tex = &kg->__tex_image_006; break;
|
||||
case 7: tex = &kg->__tex_image_007; break;
|
||||
case 8: tex = &kg->__tex_image_008; break;
|
||||
case 9: tex = &kg->__tex_image_009; break;
|
||||
case 10: tex = &kg->__tex_image_010; break;
|
||||
case 11: tex = &kg->__tex_image_011; break;
|
||||
case 12: tex = &kg->__tex_image_012; break;
|
||||
case 13: tex = &kg->__tex_image_013; break;
|
||||
case 14: tex = &kg->__tex_image_014; break;
|
||||
case 15: tex = &kg->__tex_image_015; break;
|
||||
case 16: tex = &kg->__tex_image_016; break;
|
||||
case 17: tex = &kg->__tex_image_017; break;
|
||||
case 18: tex = &kg->__tex_image_018; break;
|
||||
case 19: tex = &kg->__tex_image_019; break;
|
||||
case 20: tex = &kg->__tex_image_020; break;
|
||||
case 21: tex = &kg->__tex_image_021; break;
|
||||
case 22: tex = &kg->__tex_image_022; break;
|
||||
case 23: tex = &kg->__tex_image_023; break;
|
||||
case 24: tex = &kg->__tex_image_024; break;
|
||||
case 25: tex = &kg->__tex_image_025; break;
|
||||
case 26: tex = &kg->__tex_image_026; break;
|
||||
case 27: tex = &kg->__tex_image_027; break;
|
||||
case 28: tex = &kg->__tex_image_028; break;
|
||||
case 29: tex = &kg->__tex_image_029; break;
|
||||
case 30: tex = &kg->__tex_image_030; break;
|
||||
case 31: tex = &kg->__tex_image_031; break;
|
||||
case 32: tex = &kg->__tex_image_032; break;
|
||||
case 33: tex = &kg->__tex_image_033; break;
|
||||
case 34: tex = &kg->__tex_image_034; break;
|
||||
case 35: tex = &kg->__tex_image_035; break;
|
||||
case 36: tex = &kg->__tex_image_036; break;
|
||||
case 37: tex = &kg->__tex_image_037; break;
|
||||
case 38: tex = &kg->__tex_image_038; break;
|
||||
case 39: tex = &kg->__tex_image_039; break;
|
||||
case 40: tex = &kg->__tex_image_040; break;
|
||||
case 41: tex = &kg->__tex_image_041; break;
|
||||
case 42: tex = &kg->__tex_image_042; break;
|
||||
case 43: tex = &kg->__tex_image_043; break;
|
||||
case 44: tex = &kg->__tex_image_044; break;
|
||||
case 45: tex = &kg->__tex_image_045; break;
|
||||
case 46: tex = &kg->__tex_image_046; break;
|
||||
case 47: tex = &kg->__tex_image_047; break;
|
||||
case 48: tex = &kg->__tex_image_048; break;
|
||||
case 49: tex = &kg->__tex_image_049; break;
|
||||
case 50: tex = &kg->__tex_image_050; break;
|
||||
case 51: tex = &kg->__tex_image_051; break;
|
||||
case 52: tex = &kg->__tex_image_052; break;
|
||||
case 53: tex = &kg->__tex_image_053; break;
|
||||
case 54: tex = &kg->__tex_image_054; break;
|
||||
case 55: tex = &kg->__tex_image_055; break;
|
||||
case 56: tex = &kg->__tex_image_056; break;
|
||||
case 57: tex = &kg->__tex_image_057; break;
|
||||
case 58: tex = &kg->__tex_image_058; break;
|
||||
case 59: tex = &kg->__tex_image_059; break;
|
||||
case 60: tex = &kg->__tex_image_060; break;
|
||||
case 61: tex = &kg->__tex_image_061; break;
|
||||
case 62: tex = &kg->__tex_image_062; break;
|
||||
case 63: tex = &kg->__tex_image_063; break;
|
||||
case 64: tex = &kg->__tex_image_064; break;
|
||||
case 65: tex = &kg->__tex_image_065; break;
|
||||
case 66: tex = &kg->__tex_image_066; break;
|
||||
case 67: tex = &kg->__tex_image_067; break;
|
||||
case 68: tex = &kg->__tex_image_068; break;
|
||||
case 69: tex = &kg->__tex_image_069; break;
|
||||
case 70: tex = &kg->__tex_image_070; break;
|
||||
case 71: tex = &kg->__tex_image_071; break;
|
||||
case 72: tex = &kg->__tex_image_072; break;
|
||||
case 73: tex = &kg->__tex_image_073; break;
|
||||
case 74: tex = &kg->__tex_image_074; break;
|
||||
case 75: tex = &kg->__tex_image_075; break;
|
||||
case 76: tex = &kg->__tex_image_076; break;
|
||||
case 77: tex = &kg->__tex_image_077; break;
|
||||
case 78: tex = &kg->__tex_image_078; break;
|
||||
case 79: tex = &kg->__tex_image_079; break;
|
||||
case 80: tex = &kg->__tex_image_080; break;
|
||||
case 81: tex = &kg->__tex_image_081; break;
|
||||
case 82: tex = &kg->__tex_image_082; break;
|
||||
case 83: tex = &kg->__tex_image_083; break;
|
||||
case 84: tex = &kg->__tex_image_084; break;
|
||||
case 85: tex = &kg->__tex_image_085; break;
|
||||
case 86: tex = &kg->__tex_image_086; break;
|
||||
case 87: tex = &kg->__tex_image_087; break;
|
||||
case 88: tex = &kg->__tex_image_088; break;
|
||||
case 89: tex = &kg->__tex_image_089; break;
|
||||
case 90: tex = &kg->__tex_image_090; break;
|
||||
case 91: tex = &kg->__tex_image_091; break;
|
||||
case 92: tex = &kg->__tex_image_092; break;
|
||||
case 93: tex = &kg->__tex_image_093; break;
|
||||
case 94: tex = &kg->__tex_image_094; break;
|
||||
default: break;
|
||||
if (array_index >= 0 && array_index < MAX_BYTE_IMAGES) {
|
||||
tex = &kg->texture_byte_images[array_index];
|
||||
}
|
||||
|
||||
if(tex) {
|
||||
|
@@ -301,6 +301,10 @@ __device_inline float3 path_radiance_sum(KernelGlobals *kg, PathRadiance *L)
|
||||
|
||||
__device_inline void path_radiance_clamp(PathRadiance *L, float3 *L_sum, float clamp)
|
||||
{
|
||||
#ifdef __OSL__
|
||||
using std::isfinite;
|
||||
#endif
|
||||
|
||||
float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z);
|
||||
|
||||
if(!isfinite(sum)) {
|
||||
|
68
intern/cycles/kernel/kernel_attribute.h
Normal file
68
intern/cycles/kernel/kernel_attribute.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __KERNEL_ATTRIBUTE_CL__
|
||||
#define __KERNEL_ATTRIBUTE_CL__
|
||||
|
||||
#include "util_types.h"
|
||||
|
||||
#ifdef __OSL__
|
||||
#include <string>
|
||||
#include "util_attribute.h"
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* note: declared in kernel.h, have to add it here because kernel.h is not available */
|
||||
bool kernel_osl_use(KernelGlobals *kg);
|
||||
|
||||
__device_inline int find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
|
||||
{
|
||||
|
||||
#ifdef __OSL__
|
||||
if (kernel_osl_use(kg)) {
|
||||
/* for OSL, a hash map is used to lookup the attribute by name. */
|
||||
OSLGlobals::AttributeMap &attr_map = kg->osl.attribute_map[sd->object];
|
||||
ustring stdname(std::string("std::") + std::string(attribute_standard_name((AttributeStandard)id)));
|
||||
OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
|
||||
if (it != attr_map.end()) {
|
||||
const OSLGlobals::Attribute &osl_attr = it->second;
|
||||
/* return result */
|
||||
return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
|
||||
}
|
||||
else
|
||||
return (int)ATTR_STD_NOT_FOUND;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* for SVM, find attribute by unique id */
|
||||
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||
|
||||
while(attr_map.x != id)
|
||||
attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
|
||||
|
||||
/* return result */
|
||||
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z;
|
||||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __KERNEL_ATTRIBUTE_CL__ */
|
@@ -158,7 +158,7 @@ typedef texture_image<uchar4> texture_image_uchar4;
|
||||
#define kernel_tex_fetch_m128(tex, index) (kg->tex.fetch_m128(index))
|
||||
#define kernel_tex_fetch_m128i(tex, index) (kg->tex.fetch_m128i(index))
|
||||
#define kernel_tex_interp(tex, t, size) (kg->tex.interp(t, size))
|
||||
#define kernel_tex_image_interp(tex, x, y) (kg->tex.interp(x, y))
|
||||
#define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y))
|
||||
|
||||
#define kernel_data (kg->__data)
|
||||
|
||||
|
@@ -63,6 +63,8 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou
|
||||
out = shader_eval_background(kg, &sd, flag);
|
||||
}
|
||||
|
||||
shader_release(kg, &sd);
|
||||
|
||||
/* write output */
|
||||
output[i] = make_float4(out.x, out.y, out.z, 0.0f);
|
||||
}
|
||||
|
@@ -35,10 +35,15 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef __KERNEL_CPU__
|
||||
|
||||
#define MAX_BYTE_IMAGES 512
|
||||
#define MAX_FLOAT_IMAGES 5
|
||||
|
||||
typedef struct KernelGlobals {
|
||||
texture_image_uchar4 texture_byte_images[MAX_BYTE_IMAGES];
|
||||
texture_image_float4 texture_float_images[MAX_FLOAT_IMAGES];
|
||||
|
||||
#define KERNEL_TEX(type, ttype, name) ttype name;
|
||||
#define KERNEL_IMAGE_TEX(type, ttype, name) ttype name;
|
||||
#define KERNEL_IMAGE_TEX(type, ttype, name)
|
||||
#include "kernel_textures.h"
|
||||
|
||||
KernelData __data;
|
||||
|
@@ -172,24 +172,61 @@ __device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
|
||||
__device_inline float particle_index(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f = kernel_tex_fetch(__particles, offset);
|
||||
float4 f = kernel_tex_fetch(__particles, offset + 0);
|
||||
return f.x;
|
||||
}
|
||||
|
||||
__device float particle_age(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f = kernel_tex_fetch(__particles, offset);
|
||||
float4 f = kernel_tex_fetch(__particles, offset + 0);
|
||||
return f.y;
|
||||
}
|
||||
|
||||
__device float particle_lifetime(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f = kernel_tex_fetch(__particles, offset);
|
||||
float4 f = kernel_tex_fetch(__particles, offset + 0);
|
||||
return f.z;
|
||||
}
|
||||
|
||||
__device float particle_size(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f = kernel_tex_fetch(__particles, offset + 0);
|
||||
return f.w;
|
||||
}
|
||||
|
||||
__device float4 particle_rotation(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f = kernel_tex_fetch(__particles, offset + 1);
|
||||
return f;
|
||||
}
|
||||
|
||||
__device float3 particle_location(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f = kernel_tex_fetch(__particles, offset + 2);
|
||||
return make_float3(f.x, f.y, f.z);
|
||||
}
|
||||
|
||||
__device float3 particle_velocity(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f2 = kernel_tex_fetch(__particles, offset + 2);
|
||||
float4 f3 = kernel_tex_fetch(__particles, offset + 3);
|
||||
return make_float3(f2.w, f3.x, f3.y);
|
||||
}
|
||||
|
||||
__device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
|
||||
{
|
||||
int offset = particle*PARTICLE_SIZE;
|
||||
float4 f3 = kernel_tex_fetch(__particles, offset + 3);
|
||||
float4 f4 = kernel_tex_fetch(__particles, offset + 4);
|
||||
return make_float3(f3.z, f3.w, f4.x);
|
||||
}
|
||||
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@@ -209,6 +209,8 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
|
||||
if(ray->t != FLT_MAX)
|
||||
ray->D = normalize_len(Pend - ray->P, &ray->t);
|
||||
|
||||
shader_release(kg, &sd);
|
||||
|
||||
bounce++;
|
||||
}
|
||||
}
|
||||
@@ -294,8 +296,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
|
||||
L_transparent += average(holdout_weight*throughput);
|
||||
}
|
||||
|
||||
if(sd.flag & SD_HOLDOUT_MASK)
|
||||
if(sd.flag & SD_HOLDOUT_MASK) {
|
||||
shader_release(kg, &sd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -313,8 +317,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
|
||||
float probability = path_state_terminate_probability(kg, &state, throughput);
|
||||
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
|
||||
|
||||
if(terminate >= probability)
|
||||
if(terminate >= probability) {
|
||||
shader_release(kg, &sd);
|
||||
break;
|
||||
}
|
||||
|
||||
throughput /= probability;
|
||||
|
||||
@@ -380,8 +386,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
|
||||
#endif
|
||||
|
||||
/* no BSDF? we can stop here */
|
||||
if(!(sd.flag & SD_BSDF))
|
||||
if(!(sd.flag & SD_BSDF)) {
|
||||
shader_release(kg, &sd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* sample BSDF */
|
||||
float bsdf_pdf;
|
||||
@@ -486,8 +494,10 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
|
||||
float probability = path_state_terminate_probability(kg, &state, throughput);
|
||||
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
|
||||
|
||||
if(terminate >= probability)
|
||||
if(terminate >= probability) {
|
||||
shader_release(kg, &sd);
|
||||
break;
|
||||
}
|
||||
|
||||
throughput /= probability;
|
||||
|
||||
@@ -554,8 +564,10 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
|
||||
#endif
|
||||
|
||||
/* no BSDF? we can stop here */
|
||||
if(!(sd.flag & SD_BSDF))
|
||||
if(!(sd.flag & SD_BSDF)) {
|
||||
shader_release(kg, &sd);
|
||||
break;
|
||||
}
|
||||
|
||||
/* sample BSDF */
|
||||
float bsdf_pdf;
|
||||
@@ -661,8 +673,10 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
|
||||
L_transparent += average(holdout_weight*throughput);
|
||||
}
|
||||
|
||||
if(sd.flag & SD_HOLDOUT_MASK)
|
||||
if(sd.flag & SD_HOLDOUT_MASK) {
|
||||
shader_release(kg, &sd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -682,8 +696,10 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
|
||||
float probability = path_state_terminate_probability(kg, &state, throughput);
|
||||
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
|
||||
|
||||
if(terminate >= probability)
|
||||
if(terminate >= probability) {
|
||||
shader_release(kg, &sd);
|
||||
break;
|
||||
}
|
||||
|
||||
throughput /= probability;
|
||||
}
|
||||
@@ -693,7 +709,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
|
||||
if(kernel_data.integrator.use_ambient_occlusion) {
|
||||
int num_samples = kernel_data.integrator.ao_samples;
|
||||
float num_samples_inv = 1.0f/num_samples;
|
||||
float ao_factor = kernel_data.background.ao_factor/num_samples;
|
||||
float ao_factor = kernel_data.background.ao_factor;
|
||||
|
||||
for(int j = 0; j < num_samples; j++) {
|
||||
/* todo: solve correlation */
|
||||
@@ -842,15 +858,20 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
|
||||
path_state_next(kg, &ps, label);
|
||||
|
||||
/* setup ray */
|
||||
ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
|
||||
ray.D = bsdf_omega_in;
|
||||
ray.t = FLT_MAX;
|
||||
Ray bsdf_ray;
|
||||
|
||||
bsdf_ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
|
||||
bsdf_ray.D = bsdf_omega_in;
|
||||
bsdf_ray.t = FLT_MAX;
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
ray.dP = sd.dP;
|
||||
ray.dD = bsdf_domega_in;
|
||||
bsdf_ray.dP = sd.dP;
|
||||
bsdf_ray.dD = bsdf_domega_in;
|
||||
#endif
|
||||
#ifdef __MOTION__
|
||||
bsdf_ray.time = sd.time;
|
||||
#endif
|
||||
|
||||
kernel_path_indirect(kg, rng, sample*num_samples, ray, buffer,
|
||||
kernel_path_indirect(kg, rng, sample*num_samples, bsdf_ray, buffer,
|
||||
tp*num_samples_inv, min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L);
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "osl_shader.h"
|
||||
|
||||
#else
|
||||
#endif
|
||||
|
||||
#include "svm/bsdf.h"
|
||||
#include "svm/emissive.h"
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "svm/svm_bsdf.h"
|
||||
#include "svm/svm.h"
|
||||
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@@ -47,6 +46,11 @@ CCL_NAMESPACE_BEGIN
|
||||
__device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
|
||||
const Intersection *isect, const Ray *ray)
|
||||
{
|
||||
#ifdef __OSL__
|
||||
if (kernel_osl_use(kg))
|
||||
OSLShader::init(kg, sd);
|
||||
#endif
|
||||
|
||||
/* fetch triangle data */
|
||||
int prim = kernel_tex_fetch(__prim_index, isect->prim);
|
||||
float4 Ns = kernel_tex_fetch(__tri_normal, prim);
|
||||
@@ -130,6 +134,11 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
|
||||
const float3 P, const float3 Ng, const float3 I,
|
||||
int shader, int object, int prim, float u, float v, float t, float time)
|
||||
{
|
||||
#ifdef __OSL__
|
||||
if (kernel_osl_use(kg))
|
||||
OSLShader::init(kg, sd);
|
||||
#endif
|
||||
|
||||
/* vectors */
|
||||
sd->P = P;
|
||||
sd->N = Ng;
|
||||
@@ -234,6 +243,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
|
||||
__device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
|
||||
int object, int prim, float u, float v)
|
||||
{
|
||||
/* Note: no OSLShader::init call here, this is done in shader_setup_from_sample! */
|
||||
|
||||
float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f);
|
||||
int shader;
|
||||
|
||||
@@ -252,6 +263,11 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
|
||||
|
||||
__device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray)
|
||||
{
|
||||
#ifdef __OSL__
|
||||
if (kernel_osl_use(kg))
|
||||
OSLShader::init(kg, sd);
|
||||
#endif
|
||||
|
||||
/* vectors */
|
||||
sd->P = ray->D;
|
||||
sd->N = -sd->P;
|
||||
@@ -294,7 +310,8 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
|
||||
|
||||
#ifdef __MULTI_CLOSURE__
|
||||
|
||||
__device_inline void _shader_bsdf_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf,
|
||||
#ifdef __OSL__
|
||||
__device_inline void _shader_bsdf_multi_eval_osl(const ShaderData *sd, const float3 omega_in, float *pdf,
|
||||
int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight)
|
||||
{
|
||||
for(int i = 0; i< sd->num_closure; i++) {
|
||||
@@ -305,12 +322,36 @@ __device_inline void _shader_bsdf_multi_eval(const ShaderData *sd, const float3
|
||||
|
||||
if(CLOSURE_IS_BSDF(sc->type)) {
|
||||
float bsdf_pdf = 0.0f;
|
||||
#ifdef __OSL__
|
||||
|
||||
float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf);
|
||||
#else
|
||||
float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf);
|
||||
|
||||
if(bsdf_pdf != 0.0f) {
|
||||
bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight);
|
||||
sum_pdf += bsdf_pdf*sc->sample_weight;
|
||||
}
|
||||
|
||||
sum_sample_weight += sc->sample_weight;
|
||||
}
|
||||
}
|
||||
|
||||
*pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
__device_inline void _shader_bsdf_multi_eval_svm(const ShaderData *sd, const float3 omega_in, float *pdf,
|
||||
int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight)
|
||||
{
|
||||
for(int i = 0; i< sd->num_closure; i++) {
|
||||
if(i == skip_bsdf)
|
||||
continue;
|
||||
|
||||
const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(CLOSURE_IS_BSDF(sc->type)) {
|
||||
float bsdf_pdf = 0.0f;
|
||||
|
||||
float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf);
|
||||
|
||||
if(bsdf_pdf != 0.0f) {
|
||||
bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight);
|
||||
sum_pdf += bsdf_pdf*sc->sample_weight;
|
||||
@@ -331,7 +372,12 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
|
||||
#ifdef __MULTI_CLOSURE__
|
||||
bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
|
||||
|
||||
return _shader_bsdf_multi_eval(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
|
||||
#ifdef __OSL__
|
||||
if (kernel_osl_use(kg))
|
||||
return _shader_bsdf_multi_eval_osl(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
|
||||
else
|
||||
#endif
|
||||
return _shader_bsdf_multi_eval_svm(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
|
||||
#else
|
||||
const ShaderClosure *sc = &sd->closure;
|
||||
|
||||
@@ -384,16 +430,23 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
|
||||
|
||||
*pdf = 0.0f;
|
||||
#ifdef __OSL__
|
||||
label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf);
|
||||
#else
|
||||
label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
|
||||
if (kernel_osl_use(kg))
|
||||
label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf);
|
||||
else
|
||||
#endif
|
||||
label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
|
||||
|
||||
if(*pdf != 0.0f) {
|
||||
bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
|
||||
|
||||
if(sd->num_closure > 1) {
|
||||
float sweight = sc->sample_weight;
|
||||
_shader_bsdf_multi_eval(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
|
||||
#ifdef __OSL__
|
||||
if (kernel_osl_use(kg))
|
||||
_shader_bsdf_multi_eval_osl(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
|
||||
else
|
||||
#endif
|
||||
_shader_bsdf_multi_eval_svm(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,10 +469,12 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd,
|
||||
|
||||
*pdf = 0.0f;
|
||||
#ifdef __OSL__
|
||||
label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf);
|
||||
#else
|
||||
label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
|
||||
if (kernel_osl_use(kg))
|
||||
label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf);
|
||||
else
|
||||
#endif
|
||||
label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
|
||||
|
||||
if(*pdf != 0.0f)
|
||||
bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
|
||||
|
||||
@@ -539,10 +594,12 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
|
||||
|
||||
if(CLOSURE_IS_EMISSION(sc->type)) {
|
||||
#ifdef __OSL__
|
||||
eval += OSLShader::emissive_eval(sd, sc)*sc->weight;
|
||||
#else
|
||||
eval += svm_emissive_eval(sd, sc)*sc->weight;
|
||||
if (kernel_osl_use(kg))
|
||||
eval += OSLShader::emissive_eval(sd, sc)*sc->weight;
|
||||
else
|
||||
#endif
|
||||
eval += svm_emissive_eval(sd, sc)*sc->weight;
|
||||
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -581,17 +638,18 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
|
||||
float randb, int path_flag)
|
||||
{
|
||||
#ifdef __OSL__
|
||||
OSLShader::eval_surface(kg, sd, randb, path_flag);
|
||||
#else
|
||||
|
||||
if (kernel_osl_use(kg))
|
||||
OSLShader::eval_surface(kg, sd, randb, path_flag);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef __SVM__
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
|
||||
#else
|
||||
bsdf_diffuse_setup(sd, &sd->closure);
|
||||
sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f);
|
||||
#endif
|
||||
|
||||
bsdf_diffuse_setup(sd, &sd->closure);
|
||||
sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Background Evaluation */
|
||||
@@ -599,35 +657,37 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
|
||||
__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
|
||||
{
|
||||
#ifdef __OSL__
|
||||
return OSLShader::eval_background(kg, sd, path_flag);
|
||||
#else
|
||||
if (kernel_osl_use(kg))
|
||||
return OSLShader::eval_background(kg, sd, path_flag);
|
||||
else
|
||||
#endif
|
||||
|
||||
{
|
||||
#ifdef __SVM__
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
|
||||
|
||||
#ifdef __MULTI_CLOSURE__
|
||||
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
||||
for(int i = 0; i< sd->num_closure; i++) {
|
||||
const ShaderClosure *sc = &sd->closure[i];
|
||||
for(int i = 0; i< sd->num_closure; i++) {
|
||||
const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(CLOSURE_IS_BACKGROUND(sc->type))
|
||||
eval += sc->weight;
|
||||
if(CLOSURE_IS_BACKGROUND(sc->type))
|
||||
eval += sc->weight;
|
||||
}
|
||||
|
||||
return eval;
|
||||
#else
|
||||
if(sd->closure.type == CLOSURE_BACKGROUND_ID)
|
||||
return sd->closure.weight;
|
||||
else
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
#endif
|
||||
|
||||
#else
|
||||
return make_float3(0.8f, 0.8f, 0.8f);
|
||||
#endif
|
||||
}
|
||||
|
||||
return eval;
|
||||
#else
|
||||
if(sd->closure.type == CLOSURE_BACKGROUND_ID)
|
||||
return sd->closure.weight;
|
||||
else
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
#endif
|
||||
|
||||
#else
|
||||
return make_float3(0.8f, 0.8f, 0.8f);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Volume */
|
||||
@@ -643,10 +703,11 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
|
||||
|
||||
if(CLOSURE_IS_VOLUME(sc->type)) {
|
||||
#ifdef __OSL__
|
||||
eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out);
|
||||
#else
|
||||
eval += volume_eval_phase(sd, sc, omega_in, omega_out);
|
||||
if (kernel_osl_use(kg))
|
||||
eval += OSLShader::volume_eval_phase(sd, sc, omega_in, omega_out);
|
||||
else
|
||||
#endif
|
||||
eval += volume_eval_phase(sd, sc, omega_in, omega_out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,10 +724,11 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
|
||||
{
|
||||
#ifdef __SVM__
|
||||
#ifdef __OSL__
|
||||
OSLShader::eval_volume(kg, sd, randb, path_flag);
|
||||
#else
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
|
||||
if (kernel_osl_use(kg))
|
||||
OSLShader::eval_volume(kg, sd, randb, path_flag);
|
||||
else
|
||||
#endif
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -677,10 +739,11 @@ __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
|
||||
/* this will modify sd->P */
|
||||
#ifdef __SVM__
|
||||
#ifdef __OSL__
|
||||
OSLShader::eval_displacement(kg, sd);
|
||||
#else
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
|
||||
if (kernel_osl_use(kg))
|
||||
OSLShader::eval_displacement(kg, sd);
|
||||
else
|
||||
#endif
|
||||
svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -732,7 +795,8 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd)
|
||||
__device void shader_release(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
#ifdef __OSL__
|
||||
OSLShader::release(kg, sd);
|
||||
if (kernel_osl_use(kg))
|
||||
OSLShader::release(kg, sd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -66,12 +66,14 @@ KERNEL_TEX(float, texture_float, __filter_table)
|
||||
/* sobol */
|
||||
KERNEL_TEX(uint, texture_uint, __sobol_directions)
|
||||
|
||||
/* full-float image */
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_000)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_001)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_002)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_003)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_004)
|
||||
|
||||
/* image */
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_000)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_001)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_002)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_003)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_004)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_005)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_006)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_007)
|
||||
@@ -162,13 +164,11 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_091)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_092)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_093)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_094)
|
||||
|
||||
/* full-float image */
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_095)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_096)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_097)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_098)
|
||||
KERNEL_IMAGE_TEX(float4, texture_image_float4, __tex_image_float_099)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_095)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_096)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_097)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_098)
|
||||
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_099)
|
||||
|
||||
/* packed image (opencl) */
|
||||
KERNEL_TEX(uchar4, texture_uchar4, __tex_image_packed)
|
||||
|
@@ -16,6 +16,9 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "kernel_attribute.h"
|
||||
#include "kernel_projection.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Point on triangle for Moller-Trumbore triangles */
|
||||
@@ -181,26 +184,13 @@ __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *s
|
||||
|
||||
/* motion */
|
||||
|
||||
__device int triangle_find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
|
||||
{
|
||||
/* find attribute by unique id */
|
||||
uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
|
||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||
|
||||
while(attr_map.x != id)
|
||||
attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
|
||||
|
||||
/* return result */
|
||||
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : attr_map.z;
|
||||
}
|
||||
|
||||
__device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
float3 motion_pre = sd->P, motion_post = sd->P;
|
||||
|
||||
/* deformation motion */
|
||||
int offset_pre = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
|
||||
int offset_post = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_POST);
|
||||
int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
|
||||
int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST);
|
||||
|
||||
if(offset_pre != ATTR_STD_NOT_FOUND)
|
||||
motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
|
||||
@@ -259,7 +249,7 @@ __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
|
||||
|
||||
__device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
int offset_uv = triangle_find_attribute(kg, sd, ATTR_STD_UV);
|
||||
int offset_uv = find_attribute(kg, sd, ATTR_STD_UV);
|
||||
|
||||
if(offset_uv == ATTR_STD_NOT_FOUND)
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
@@ -33,7 +33,7 @@ CCL_NAMESPACE_BEGIN
|
||||
#define LIGHT_SIZE 4
|
||||
#define FILTER_TABLE_SIZE 256
|
||||
#define RAMP_TABLE_SIZE 256
|
||||
#define PARTICLE_SIZE 1
|
||||
#define PARTICLE_SIZE 5
|
||||
#define TIME_INVALID FLT_MAX
|
||||
|
||||
/* device capabilities */
|
||||
@@ -352,22 +352,6 @@ typedef enum AttributeElement {
|
||||
ATTR_ELEMENT_NONE
|
||||
} AttributeElement;
|
||||
|
||||
typedef enum AttributeStandard {
|
||||
ATTR_STD_NONE = 0,
|
||||
ATTR_STD_VERTEX_NORMAL,
|
||||
ATTR_STD_FACE_NORMAL,
|
||||
ATTR_STD_UV,
|
||||
ATTR_STD_GENERATED,
|
||||
ATTR_STD_POSITION_UNDEFORMED,
|
||||
ATTR_STD_POSITION_UNDISPLACED,
|
||||
ATTR_STD_MOTION_PRE,
|
||||
ATTR_STD_MOTION_POST,
|
||||
ATTR_STD_PARTICLE,
|
||||
ATTR_STD_NUM,
|
||||
|
||||
ATTR_STD_NOT_FOUND = ~0
|
||||
} AttributeStandard;
|
||||
|
||||
/* Closure data */
|
||||
|
||||
#define MAX_CLOSURE 8
|
||||
@@ -382,10 +366,9 @@ typedef struct ShaderClosure {
|
||||
|
||||
#ifdef __OSL__
|
||||
void *prim;
|
||||
#else
|
||||
#endif
|
||||
float data0;
|
||||
float data1;
|
||||
#endif
|
||||
|
||||
} ShaderClosure;
|
||||
|
||||
|
@@ -13,6 +13,7 @@ set(SRC
|
||||
bsdf_ashikhmin_velvet.cpp
|
||||
bsdf_diffuse.cpp
|
||||
bsdf_oren_nayar.cpp
|
||||
bsdf_phong.cpp
|
||||
bsdf_microfacet.cpp
|
||||
bsdf_reflection.cpp
|
||||
bsdf_refraction.cpp
|
||||
|
277
intern/cycles/kernel/osl/bsdf_phong.cpp
Normal file
277
intern/cycles/kernel/osl/bsdf_phong.cpp
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Adapted from Open Shading Language with this license:
|
||||
*
|
||||
* Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Modifications Copyright 2012, Blender Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Sony Pictures Imageworks nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <OpenImageIO/fmath.h>
|
||||
|
||||
#include <OSL/genclosure.h>
|
||||
#include "osl_closures.h"
|
||||
#include "util_math.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
using namespace OSL;
|
||||
|
||||
// vanilla phong - leaks energy at grazing angles
|
||||
// see Global Illumination Compendium entry (66)
|
||||
class PhongClosure : public BSDFClosure {
|
||||
public:
|
||||
Vec3 m_N;
|
||||
float m_exponent;
|
||||
PhongClosure() : BSDFClosure(Labels::GLOSSY) { }
|
||||
|
||||
void setup() {};
|
||||
|
||||
bool mergeable (const ClosurePrimitive *other) const {
|
||||
const PhongClosure *comp = (const PhongClosure *)other;
|
||||
return m_N == comp->m_N && m_exponent == comp->m_exponent &&
|
||||
BSDFClosure::mergeable(other);
|
||||
}
|
||||
|
||||
size_t memsize () const { return sizeof(*this); }
|
||||
|
||||
const char *name () const { return "phong"; }
|
||||
|
||||
void print_on (std::ostream &out) const {
|
||||
out << name() << " ((";
|
||||
out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||
out << m_exponent << ")";
|
||||
}
|
||||
|
||||
float albedo (const Vec3 &omega_out) const
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||
{
|
||||
float cosNI = m_N.dot(omega_in);
|
||||
float cosNO = m_N.dot(omega_out);
|
||||
if (cosNI > 0 && cosNO > 0) {
|
||||
// reflect the view vector
|
||||
Vec3 R = (2 * cosNO) * m_N - omega_out;
|
||||
float cosRI = R.dot(omega_in);
|
||||
if (cosRI > 0) {
|
||||
float common = 0.5f * (float) M_1_PI * powf(cosRI, m_exponent);
|
||||
float out = cosNI * (m_exponent + 2) * common;
|
||||
pdf = (m_exponent + 1) * common;
|
||||
return Color3 (out, out, out);
|
||||
}
|
||||
}
|
||||
return Color3 (0, 0, 0);
|
||||
}
|
||||
|
||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||
{
|
||||
return Color3 (0, 0, 0);
|
||||
}
|
||||
|
||||
ustring sample (const Vec3 &Ng,
|
||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||
float randu, float randv,
|
||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||
float &pdf, Color3 &eval) const
|
||||
{
|
||||
float cosNO = m_N.dot(omega_out);
|
||||
if (cosNO > 0) {
|
||||
// reflect the view vector
|
||||
Vec3 R = (2 * cosNO) * m_N - omega_out;
|
||||
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
|
||||
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
|
||||
Vec3 T, B;
|
||||
make_orthonormals (R, T, B);
|
||||
float phi = 2 * (float) M_PI * randu;
|
||||
float cosTheta = powf(randv, 1 / (m_exponent + 1));
|
||||
float sinTheta2 = 1 - cosTheta * cosTheta;
|
||||
float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
|
||||
omega_in = (cosf(phi) * sinTheta) * T +
|
||||
(sinf(phi) * sinTheta) * B +
|
||||
( cosTheta) * R;
|
||||
if (Ng.dot(omega_in) > 0)
|
||||
{
|
||||
// common terms for pdf and eval
|
||||
float cosNI = m_N.dot(omega_in);
|
||||
// make sure the direction we chose is still in the right hemisphere
|
||||
if (cosNI > 0)
|
||||
{
|
||||
float common = 0.5f * (float) M_1_PI * powf(cosTheta, m_exponent);
|
||||
pdf = (m_exponent + 1) * common;
|
||||
float out = cosNI * (m_exponent + 2) * common;
|
||||
eval.setValue(out, out, out);
|
||||
// Since there is some blur to this reflection, make the
|
||||
// derivatives a bit bigger. In theory this varies with the
|
||||
// exponent but the exact relationship is complex and
|
||||
// requires more ops than are practical.
|
||||
domega_in_dx *= 10;
|
||||
domega_in_dy *= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Labels::REFLECT;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class PhongRampClosure : public BSDFClosure {
|
||||
public:
|
||||
static const int MAXCOLORS = 8;
|
||||
Vec3 m_N;
|
||||
float m_exponent;
|
||||
Color3 m_colors[MAXCOLORS];
|
||||
PhongRampClosure() : BSDFClosure(Labels::GLOSSY) { }
|
||||
|
||||
void setup() {};
|
||||
|
||||
bool mergeable (const ClosurePrimitive *other) const {
|
||||
const PhongRampClosure *comp = (const PhongRampClosure *)other;
|
||||
if (! (m_N == comp->m_N && m_exponent == comp->m_exponent &&
|
||||
BSDFClosure::mergeable(other)))
|
||||
return false;
|
||||
for (int i = 0; i < MAXCOLORS; ++i)
|
||||
if (m_colors[i] != comp->m_colors[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t memsize () const { return sizeof(*this); }
|
||||
|
||||
const char *name () const { return "phong_ramp"; }
|
||||
|
||||
void print_on (std::ostream &out) const {
|
||||
out << name() << " ((";
|
||||
out << m_N[0] << ", " << m_N[1] << ", " << m_N[2] << "), ";
|
||||
out << m_exponent << ")";
|
||||
}
|
||||
|
||||
Color3 get_color (float pos) const
|
||||
{
|
||||
float npos = pos * (float)(MAXCOLORS - 1);
|
||||
int ipos = (int)npos;
|
||||
if (ipos >= (MAXCOLORS - 1))
|
||||
return m_colors[MAXCOLORS - 1];
|
||||
float offset = npos - (float)ipos;
|
||||
return m_colors[ipos] * (1.0f - offset) + m_colors[ipos+1] * offset;
|
||||
}
|
||||
|
||||
float albedo (const Vec3 &omega_out) const
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
Color3 eval_reflect (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||
{
|
||||
float cosNI = m_N.dot(omega_in);
|
||||
float cosNO = m_N.dot(omega_out);
|
||||
if (cosNI > 0 && cosNO > 0) {
|
||||
// reflect the view vector
|
||||
Vec3 R = (2 * cosNO) * m_N - omega_out;
|
||||
float cosRI = R.dot(omega_in);
|
||||
if (cosRI > 0) {
|
||||
float cosp = powf(cosRI, m_exponent);
|
||||
float common = 0.5f * (float) M_1_PI * cosp;
|
||||
float out = cosNI * (m_exponent + 2) * common;
|
||||
pdf = (m_exponent + 1) * common;
|
||||
return get_color(cosp) * out;
|
||||
}
|
||||
}
|
||||
return Color3 (0, 0, 0);
|
||||
}
|
||||
|
||||
Color3 eval_transmit (const Vec3 &omega_out, const Vec3 &omega_in, float& pdf) const
|
||||
{
|
||||
return Color3 (0, 0, 0);
|
||||
}
|
||||
|
||||
ustring sample (const Vec3 &Ng,
|
||||
const Vec3 &omega_out, const Vec3 &domega_out_dx, const Vec3 &domega_out_dy,
|
||||
float randu, float randv,
|
||||
Vec3 &omega_in, Vec3 &domega_in_dx, Vec3 &domega_in_dy,
|
||||
float &pdf, Color3 &eval) const
|
||||
{
|
||||
float cosNO = m_N.dot(omega_out);
|
||||
if (cosNO > 0) {
|
||||
// reflect the view vector
|
||||
Vec3 R = (2 * cosNO) * m_N - omega_out;
|
||||
domega_in_dx = (2 * m_N.dot(domega_out_dx)) * m_N - domega_out_dx;
|
||||
domega_in_dy = (2 * m_N.dot(domega_out_dy)) * m_N - domega_out_dy;
|
||||
Vec3 T, B;
|
||||
make_orthonormals (R, T, B);
|
||||
float phi = 2 * (float) M_PI * randu;
|
||||
float cosTheta = powf(randv, 1 / (m_exponent + 1));
|
||||
float sinTheta2 = 1 - cosTheta * cosTheta;
|
||||
float sinTheta = sinTheta2 > 0 ? sqrtf(sinTheta2) : 0;
|
||||
omega_in = (cosf(phi) * sinTheta) * T +
|
||||
(sinf(phi) * sinTheta) * B +
|
||||
( cosTheta) * R;
|
||||
if (Ng.dot(omega_in) > 0)
|
||||
{
|
||||
// common terms for pdf and eval
|
||||
float cosNI = m_N.dot(omega_in);
|
||||
// make sure the direction we chose is still in the right hemisphere
|
||||
if (cosNI > 0)
|
||||
{
|
||||
float cosp = powf(cosTheta, m_exponent);
|
||||
float common = 0.5f * (float) M_1_PI * cosp;
|
||||
pdf = (m_exponent + 1) * common;
|
||||
float out = cosNI * (m_exponent + 2) * common;
|
||||
eval = get_color(cosp) * out;
|
||||
// Since there is some blur to this reflection, make the
|
||||
// derivatives a bit bigger. In theory this varies with the
|
||||
// exponent but the exact relationship is complex and
|
||||
// requires more ops than are practical.
|
||||
domega_in_dx *= 10;
|
||||
domega_in_dy *= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Labels::REFLECT;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
ClosureParam bsdf_phong_params[] = {
|
||||
CLOSURE_VECTOR_PARAM(PhongClosure, m_N),
|
||||
CLOSURE_FLOAT_PARAM (PhongClosure, m_exponent),
|
||||
CLOSURE_STRING_KEYPARAM("label"),
|
||||
CLOSURE_FINISH_PARAM(PhongClosure) };
|
||||
|
||||
ClosureParam bsdf_phong_ramp_params[] = {
|
||||
CLOSURE_VECTOR_PARAM (PhongRampClosure, m_N),
|
||||
CLOSURE_FLOAT_PARAM (PhongRampClosure, m_exponent),
|
||||
CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, m_colors, PhongRampClosure::MAXCOLORS),
|
||||
CLOSURE_STRING_KEYPARAM("label"),
|
||||
CLOSURE_FINISH_PARAM (PhongRampClosure) };
|
||||
|
||||
CLOSURE_PREPARE(bsdf_phong_prepare, PhongClosure)
|
||||
CLOSURE_PREPARE(bsdf_phong_ramp_prepare, PhongRampClosure)
|
||||
|
||||
CCL_NAMESPACE_END
|
@@ -5,9 +5,11 @@ set(SRC_OSL
|
||||
node_add_closure.osl
|
||||
node_attribute.osl
|
||||
node_background.osl
|
||||
node_brick_texture.osl
|
||||
node_bump.osl
|
||||
node_camera.osl
|
||||
node_checker_texture.osl
|
||||
node_combine_rgb.osl
|
||||
node_convert_from_color.osl
|
||||
node_convert_from_float.osl
|
||||
node_convert_from_normal.osl
|
||||
@@ -23,6 +25,7 @@ set(SRC_OSL
|
||||
node_geometry.osl
|
||||
node_glass_bsdf.osl
|
||||
node_glossy_bsdf.osl
|
||||
node_holdout.osl
|
||||
node_hsv.osl
|
||||
node_image_texture.osl
|
||||
node_invert.osl
|
||||
@@ -34,12 +37,13 @@ set(SRC_OSL
|
||||
node_mix_closure.osl
|
||||
node_musgrave_texture.osl
|
||||
node_normal.osl
|
||||
node_blend_weight_texture.osl
|
||||
node_noise_texture.osl
|
||||
node_object_info.osl
|
||||
node_output_displacement.osl
|
||||
node_output_surface.osl
|
||||
node_output_volume.osl
|
||||
node_sepcomb_rgb.osl
|
||||
node_particle_info.osl
|
||||
node_separate_rgb.osl
|
||||
node_sky_texture.osl
|
||||
node_texture_coordinate.osl
|
||||
node_translucent_bsdf.osl
|
||||
@@ -57,6 +61,7 @@ set(SRC_OSL_HEADERS
|
||||
node_color.h
|
||||
node_fresnel.h
|
||||
stdosl.h
|
||||
oslutil.h
|
||||
)
|
||||
|
||||
set(SRC_OSO
|
||||
@@ -82,4 +87,5 @@ endforeach()
|
||||
|
||||
add_custom_target(shader ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS})
|
||||
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader)
|
||||
# CMAKE_CURRENT_SOURCE_DIR is already included in OSO paths
|
||||
delayed_install("" "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader)
|
||||
|
94
intern/cycles/kernel/osl/nodes/node_brick_texture.osl
Normal file
94
intern/cycles/kernel/osl/nodes/node_brick_texture.osl
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2012, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "stdosl.h"
|
||||
#include "node_texture.h"
|
||||
|
||||
/* Brick */
|
||||
|
||||
float brick_noise(int n) /* fast integer noise */
|
||||
{
|
||||
int nn;
|
||||
n = (n >> 13) ^ n;
|
||||
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 2147483647;
|
||||
return 0.5 * ((float)nn / 1073741824.0);
|
||||
}
|
||||
|
||||
float brick(point p, float mortar_size, float bias,
|
||||
float BrickWidth, float row_height, float offset_amount, int offset_frequency,
|
||||
float squash_amount, int squash_frequency, float tint)
|
||||
{
|
||||
int bricknum, rownum;
|
||||
float offset = 0.0;
|
||||
float brick_width = BrickWidth;
|
||||
float x, y;
|
||||
|
||||
rownum = (int)floor(p[1] / row_height);
|
||||
|
||||
if(offset_frequency && squash_frequency) {
|
||||
brick_width *= ((int)(rownum) % squash_frequency ) ? 1.0 : squash_amount; /* squash */
|
||||
offset = ((int)(rownum) % offset_frequency ) ? 0 : (brick_width*offset_amount); /* offset */
|
||||
}
|
||||
|
||||
bricknum = (int)floor((p[0]+offset) / brick_width);
|
||||
|
||||
x = (p[0]+offset) - brick_width*bricknum;
|
||||
y = p[1] - row_height*rownum;
|
||||
|
||||
tint = clamp((brick_noise((rownum << 16) + (bricknum & 65535)) + bias), 0.0, 1.0);
|
||||
|
||||
return (x < mortar_size || y < mortar_size ||
|
||||
x > (brick_width - mortar_size) ||
|
||||
y > (row_height - mortar_size)) ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
shader node_brick_texture(
|
||||
float Offset = 0.5,
|
||||
int OffsetFrequency = 2,
|
||||
float Squash = 1.0,
|
||||
int SquashFrequency = 1,
|
||||
point Vector = P,
|
||||
color Color1 = color(0.2, 0.2, 0.2),
|
||||
color Color2 = color(0.8, 0.8, 0.8),
|
||||
color Mortar = color(0.0, 0.0, 0.0),
|
||||
float Scale = 5.0,
|
||||
float MortarSize = 0.02,
|
||||
float Bias = 0.0,
|
||||
float BrickWidth = 0.5,
|
||||
float RowHeight = 0.25,
|
||||
output float Fac = 0.0,
|
||||
output color Color = color(0.2, 0.2, 0.2))
|
||||
{
|
||||
float tint = 0.0;
|
||||
color Col = Color1;
|
||||
|
||||
Fac = brick(Vector*Scale, MortarSize, Bias, BrickWidth, RowHeight,
|
||||
Offset, OffsetFrequency, Squash, SquashFrequency, tint);
|
||||
|
||||
if(Fac != 1.0) {
|
||||
float facm = 1.0 - tint;
|
||||
|
||||
Col[0] = facm * (Color1[0]) + tint * Color2[0];
|
||||
Col[1] = facm * (Color1[1]) + tint * Color2[1];
|
||||
Col[2] = facm * (Color1[2]) + tint * Color2[2];
|
||||
}
|
||||
|
||||
Color = (Fac == 1.0) ? Mortar: Col;
|
||||
|
||||
}
|
||||
|
@@ -20,15 +20,16 @@
|
||||
|
||||
shader node_brightness(
|
||||
color ColorIn = color(0.8, 0.8, 0.8),
|
||||
float Bright = 0.0,
|
||||
float Brightness = 0.0,
|
||||
float Contrast = 0.0,
|
||||
output ColorOut = color(0.8, 0.8, 0.8)
|
||||
output color ColorOut = color(0.8, 0.8, 0.8))
|
||||
{
|
||||
float delta = Contrast * (1.0/200.0);
|
||||
float a = 1.0 - delta * 2.0;
|
||||
float b;
|
||||
|
||||
Bright *= 1.0/100.0;
|
||||
/* input value is a percentage */
|
||||
float bright_factor = Brightness / 100.0;
|
||||
|
||||
/*
|
||||
* The algorithm is by Werner D. Streidt
|
||||
@@ -38,11 +39,11 @@ shader node_brightness(
|
||||
|
||||
if (Contrast > 0.0) {
|
||||
a = (a < 0.0 ? 1.0/a : 0.0);
|
||||
b = a * (Brightness - delta);
|
||||
b = a * (bright_factor - delta);
|
||||
}
|
||||
else {
|
||||
delta *= -1.0;
|
||||
b = a * (Brightness + delta);
|
||||
b = a * (bright_factor + delta);
|
||||
}
|
||||
|
||||
ColorOut = a * ColorIn + b;
|
||||
|
@@ -49,10 +49,10 @@ shader node_checker_texture(
|
||||
{
|
||||
Fac = checker(Vector*Scale);
|
||||
if(Fac == 1.0) {
|
||||
Color = color(Color1, Color1, Color1);
|
||||
Color = Color1;
|
||||
}
|
||||
else {
|
||||
Color = color(Color2, Color2, Color2);
|
||||
Color = Color2;
|
||||
}
|
||||
}
|
||||
|
||||
|
29
intern/cycles/kernel/osl/nodes/node_combine_rgb.osl
Normal file
29
intern/cycles/kernel/osl/nodes/node_combine_rgb.osl
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "stdosl.h"
|
||||
|
||||
shader node_combine_rgb(
|
||||
float R = 0.0,
|
||||
float G = 0.0,
|
||||
float B = 0.0,
|
||||
output color Image = color(0.8, 0.8, 0.8))
|
||||
{
|
||||
Image = color(R, G, B);
|
||||
}
|
||||
|
@@ -21,13 +21,7 @@
|
||||
shader node_gamma(
|
||||
color ColorIn = color(0.8, 0.8, 0.8),
|
||||
float Gamma = 1.0,
|
||||
output ColorOut = color(0.8, 0.8, 0.8)
|
||||
output color ColorOut = color(0.0, 0.0, 0.0))
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<3;i++) {
|
||||
if (ColorIn[i] > 0.0)
|
||||
ColorIn[i] = powf(ColorIn[i], Gamma);
|
||||
}
|
||||
|
||||
ColorOut = ColorIn;
|
||||
ColorOut = pow(ColorIn, Gamma);
|
||||
}
|
||||
|
@@ -34,8 +34,8 @@ shader node_glass_bsdf(
|
||||
if(distribution == "Sharp")
|
||||
BSDF = Color*(Fr*reflection(Normal) + (1.0-Fr)*refraction(Normal, eta));
|
||||
else if(distribution == "Beckmann")
|
||||
BSDF = Color*(Fr*microfacet_beckmann(Normal, Roughness) + (1.0-Fr)*microfacet_beckmann_refraction(Normal, Roughness, eta));
|
||||
BSDF = Color*(Fr*microfacet_beckmann(Normal, Roughness, eta) + (1.0-Fr)*microfacet_beckmann_refraction(Normal, Roughness, eta));
|
||||
else if(distribution == "GGX")
|
||||
BSDF = Color*(Fr*microfacet_ggx(Normal, Roughness) + (1.0-Fr)*microfacet_ggx_refraction(Normal, Roughness, eta));
|
||||
BSDF = Color*(Fr*microfacet_ggx(Normal, Roughness, eta) + (1.0-Fr)*microfacet_ggx_refraction(Normal, Roughness, eta));
|
||||
}
|
||||
|
||||
|
@@ -29,9 +29,9 @@ shader node_glossy_bsdf(
|
||||
if(distribution == "Sharp")
|
||||
BSDF = Color*reflection(Normal);
|
||||
else if(distribution == "Beckmann")
|
||||
BSDF = Color*microfacet_beckmann(Normal, Roughness);
|
||||
BSDF = Color*microfacet_beckmann(Normal, Roughness, 1.0);
|
||||
else if(distribution == "GGX")
|
||||
BSDF = Color*microfacet_ggx(Normal, Roughness);
|
||||
BSDF = Color*microfacet_ggx(Normal, Roughness, 1.0);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -21,46 +21,40 @@
|
||||
|
||||
/* Gradient */
|
||||
|
||||
float gradient(point p, string progression, string axis)
|
||||
float gradient(point p, string type)
|
||||
{
|
||||
float x, y;
|
||||
|
||||
if(axis == "Vertical") {
|
||||
x= p[1];
|
||||
y= p[0];
|
||||
}
|
||||
else {
|
||||
x= p[0];
|
||||
y= p[1];
|
||||
}
|
||||
|
||||
x = p[0];
|
||||
y = p[1];
|
||||
|
||||
float result = 0.0;
|
||||
|
||||
if(progression == "Linear") {
|
||||
if(type == "Linear") {
|
||||
result = (1.0 + x)/2.0;
|
||||
}
|
||||
else if(progression == "Quadratic") {
|
||||
else if(type == "Quadratic") {
|
||||
float r = max((1.0 + x)/2.0, 0.0);
|
||||
result = r*r;
|
||||
}
|
||||
else if(progression == "Easing") {
|
||||
else if(type == "Easing") {
|
||||
float r = min(max((1.0 + x)/2.0, 0.0), 1.0);
|
||||
float t = r*r;
|
||||
|
||||
result = (3.0*t - 2.0*t*r);
|
||||
}
|
||||
else if(progression == "Diagonal") {
|
||||
else if(type == "Diagonal") {
|
||||
result = (2.0 + x + y)/4.0;
|
||||
}
|
||||
else if(progression == "Radial") {
|
||||
else if(type == "Radial") {
|
||||
result = atan2(y, x)/(2*M_PI) + 0.5;
|
||||
}
|
||||
else {
|
||||
float r = max(1.0 - sqrt(x*x + y*y + p[2]*p[2]), 0.0);
|
||||
|
||||
if(progression == "Quadratic Sphere")
|
||||
if(type == "Quadratic Sphere")
|
||||
result = r*r;
|
||||
else if(progression == "Spherical")
|
||||
else if(type == "Spherical")
|
||||
result = r;
|
||||
}
|
||||
|
||||
@@ -68,11 +62,12 @@ float gradient(point p, string progression, string axis)
|
||||
}
|
||||
|
||||
shader node_gradient_texture(
|
||||
string Progression = "Linear",
|
||||
string Axis = "Horizontal",
|
||||
string Type = "Linear",
|
||||
point Vector = P,
|
||||
output float Fac = 0.0)
|
||||
output float Fac = 0.0,
|
||||
output color Color = color(0.0, 0.0, 0.0))
|
||||
{
|
||||
Fac = gradient(Vector, Progression, Axis);
|
||||
Fac = gradient(Vector, Type);
|
||||
Color = color(Fac, Fac, Fac);
|
||||
}
|
||||
|
||||
|
@@ -18,11 +18,9 @@
|
||||
|
||||
#include "stdosl.h"
|
||||
|
||||
shader node_background(
|
||||
color Color = color(0.8, 0.8, 0.8),
|
||||
float Strength = 1.0,
|
||||
output closure color Background = background())
|
||||
shader node_holdout(
|
||||
output closure color Holdout = holdout())
|
||||
{
|
||||
Background = Color*Strength*background();
|
||||
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,7 @@
|
||||
shader node_invert(
|
||||
float Fac = 1.0,
|
||||
color ColorIn = color(0.8, 0.8, 0.8),
|
||||
output ColorOut = color(0.8, 0.8, 0.8)
|
||||
output color ColorOut = color(0.8, 0.8, 0.8))
|
||||
{
|
||||
color ColorInv = color(1.0) - ColorIn;
|
||||
ColorOut = mix(ColorIn, ColorInv, Fac);
|
||||
|
@@ -40,6 +40,7 @@ float safe_log(float a, float b)
|
||||
|
||||
shader node_math(
|
||||
string type = "Add",
|
||||
int Clamp = 0,
|
||||
float Value1 = 0.0,
|
||||
float Value2 = 0.0,
|
||||
output float Value = 0.0)
|
||||
@@ -80,5 +81,8 @@ shader node_math(
|
||||
Value = Value1 < Value2;
|
||||
if(type == "Greater Than")
|
||||
Value = Value1 > Value2;
|
||||
|
||||
if(Clamp)
|
||||
Value = clamp(Value1, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
@@ -267,8 +267,20 @@ color node_mix_linear(float t, color col1, color col2)
|
||||
return outcol;
|
||||
}
|
||||
|
||||
color node_mix_clamp(color col)
|
||||
{
|
||||
color outcol = col;
|
||||
|
||||
outcol[0] = clamp(col[0], 0.0, 1.0);
|
||||
outcol[1] = clamp(col[2], 0.0, 1.0);
|
||||
outcol[2] = clamp(col[2], 0.0, 1.0);
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
shader node_mix(
|
||||
string type = "Mix",
|
||||
int Clamp = 0,
|
||||
float Fac = 0.5,
|
||||
color Color1 = color(0.0, 0.0, 0.0),
|
||||
color Color2 = color(0.0, 0.0, 0.0),
|
||||
@@ -312,5 +324,8 @@ shader node_mix(
|
||||
Color = node_mix_soft(t, Color1, Color2);
|
||||
if(type == "Linear Light")
|
||||
Color = node_mix_linear(t, Color1, Color2);
|
||||
|
||||
if(Clamp)
|
||||
Color = node_mix_clamp(Color);
|
||||
}
|
||||
|
||||
|
@@ -186,32 +186,35 @@ float noise_musgrave_ridged_multi_fractal(point p, string basis, float H, float
|
||||
|
||||
shader node_musgrave_texture(
|
||||
string Type = "fBM",
|
||||
string Basis = "Perlin",
|
||||
float Dimension = 2.0,
|
||||
float Lacunarity = 1.0,
|
||||
float Octaves = 2.0,
|
||||
float Detail = 2.0,
|
||||
float Offset = 0.0,
|
||||
float Intensity = 1.0,
|
||||
float Gain = 1.0,
|
||||
float Scale = 5.0,
|
||||
point Vector = P,
|
||||
output float Fac = 0.0)
|
||||
output float Fac = 0.0,
|
||||
output color Color = color(0.0, 0.0, 0.0))
|
||||
{
|
||||
float dimension = max(Dimension, 0.0);
|
||||
float octaves = max(Octaves, 0.0);
|
||||
float dimension = max(Dimension, 1e-5);
|
||||
float octaves = clamp(Detail, 0.0, 16.0);
|
||||
float lacunarity = max(Lacunarity, 1e-5);
|
||||
string Basis = "Perlin";
|
||||
float intensity = 1.0;
|
||||
|
||||
point p = Vector*Scale;
|
||||
|
||||
if(Type == "Multifractal")
|
||||
Fac = Intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves);
|
||||
Fac = intensity*noise_musgrave_multi_fractal(p, Basis, dimension, lacunarity, octaves);
|
||||
else if(Type == "fBM")
|
||||
Fac = Intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves);
|
||||
Fac = intensity*noise_musgrave_fBm(p, Basis, dimension, lacunarity, octaves);
|
||||
else if(Type == "Hybrid Multifractal")
|
||||
Fac = Intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
|
||||
Fac = intensity*noise_musgrave_hybrid_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
|
||||
else if(Type == "Ridged Multifractal")
|
||||
Fac = Intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
|
||||
Fac = intensity*noise_musgrave_ridged_multi_fractal(p, Basis, dimension, lacunarity, octaves, Offset, Gain);
|
||||
else if(Type == "Hetero Terrain")
|
||||
Fac = Intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset);
|
||||
Fac = intensity*noise_musgrave_hetero_terrain(p, Basis, dimension, lacunarity, octaves, Offset);
|
||||
|
||||
Color = color(Fac, Fac, Fac);
|
||||
}
|
||||
|
||||
|
@@ -21,13 +21,12 @@
|
||||
|
||||
/* Noise */
|
||||
|
||||
float noise(point p, string basis, float distortion, float detail)
|
||||
float noise(point p, string basis, float distortion, float detail, float fac, color Color)
|
||||
{
|
||||
point r;
|
||||
int hard = 0;
|
||||
float fac = 0.0;
|
||||
|
||||
if(distortion != 0.0( {
|
||||
if(distortion != 0.0) {
|
||||
r[0] = noise_basis(p + point(13.5), basis) * distortion;
|
||||
r[1] = noise_basis(p, basis) * distortion;
|
||||
r[2] = noise_basis(p - point(13.5), basis) * distortion;
|
||||
@@ -37,23 +36,21 @@ float noise(point p, string basis, float distortion, float detail)
|
||||
|
||||
fac = noise_turbulence(p, basis, detail, hard);
|
||||
|
||||
Color = color(fac, noise_turbulence(point(p[1], p[0], p[2]), basis, detail, hard),
|
||||
noise_turbulence(point(p[1], p[2], p[0]), basis, detail, hard));
|
||||
|
||||
return fac;
|
||||
|
||||
/*
|
||||
Color[0] = Fac;
|
||||
Color[1] = noise_turbulence(point(p[1], p[0], p[2]), basis, detail, hard);
|
||||
Color[2] = noise_turbulence(point(p[1], p[2], p[0]), basis, detail, hard);
|
||||
*/
|
||||
}
|
||||
|
||||
shader node_noise_texture(
|
||||
string Basis = "Perlin",
|
||||
float Distortion = 0.0,
|
||||
float Scale = 5.0,
|
||||
float Detail = 2.0,
|
||||
point Vector = P,
|
||||
output float Fac = 0.0)
|
||||
output float Fac = 0.0,
|
||||
output color Color = color(0.2, 0.2, 0.2))
|
||||
{
|
||||
Fac = noise(Vector*Scale, Basis, Distortion, Detail);
|
||||
string Basis = "Perlin";
|
||||
Fac = noise(Vector*Scale, Basis, Distortion, Detail, Fac, Color);
|
||||
}
|
||||
|
||||
|
@@ -22,10 +22,9 @@ shader node_normal(
|
||||
normal Direction = normal(0.0, 0.0, 0.0),
|
||||
normal NormalIn = normal(0.0, 0.0, 0.0),
|
||||
output normal NormalOut = normal(0.0, 0.0, 0.0),
|
||||
output float Dot = 1.0
|
||||
output float Dot = 1.0)
|
||||
{
|
||||
Direction = normalize(Direction);
|
||||
NormalOut = Direction;
|
||||
Dot = dot(Direction, NormalIn);
|
||||
NormalOut = normalize(Direction);
|
||||
Dot = dot(NormalOut, NormalIn);
|
||||
}
|
||||
|
||||
|
33
intern/cycles/kernel/osl/nodes/node_object_info.osl
Normal file
33
intern/cycles/kernel/osl/nodes/node_object_info.osl
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "stdosl.h"
|
||||
|
||||
shader node_object_info(
|
||||
output point Location = point(0.0, 0.0, 0.0),
|
||||
output float ObjectIndex = 0.0,
|
||||
output float MaterialIndex = 0.0,
|
||||
output float Random = 0.0
|
||||
)
|
||||
{
|
||||
getattribute("std::object_location", Location);
|
||||
getattribute("std::object_index", ObjectIndex);
|
||||
getattribute("std::material_index", MaterialIndex);
|
||||
getattribute("std::object_random", Random);
|
||||
}
|
||||
|
39
intern/cycles/kernel/osl/nodes/node_particle_info.osl
Normal file
39
intern/cycles/kernel/osl/nodes/node_particle_info.osl
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2011, Blender Foundation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "stdosl.h"
|
||||
|
||||
shader node_particle_info(
|
||||
output float Index = 0.0,
|
||||
output float Age = 0.0,
|
||||
output float Lifetime = 0.0,
|
||||
output point Location = point(0.0, 0.0, 0.0),
|
||||
output float Size = 0.0,
|
||||
output vector Velocity = point(0.0, 0.0, 0.0),
|
||||
output vector AngularVelocity = point(0.0, 0.0, 0.0)
|
||||
)
|
||||
{
|
||||
getattribute("std::particle_index", Index);
|
||||
getattribute("std::particle_age", Age);
|
||||
getattribute("std::particle_lifetime", Lifetime);
|
||||
getattribute("std::particle_location", Location);
|
||||
getattribute("std::particle_size", Size);
|
||||
getattribute("std::particle_velocity", Velocity);
|
||||
getattribute("std::particle_angular_velocity", AngularVelocity);
|
||||
}
|
||||
|
@@ -24,17 +24,7 @@ shader node_separate_rgb(
|
||||
output float G = 0.0,
|
||||
output float B = 0.0)
|
||||
{
|
||||
R = Image[0];
|
||||
G = Image[1];
|
||||
B = Image[2];
|
||||
R = Image[0];
|
||||
G = Image[1];
|
||||
B = Image[2];
|
||||
}
|
||||
|
||||
shader node_combine_rgb(
|
||||
float R = 0.0,
|
||||
float G = 0.0,
|
||||
float B = 0.0,
|
||||
output color Image = color(0.8, 0.8, 0.8)
|
||||
{
|
||||
Image = color(R, G, B)
|
||||
}
|
||||
|
@@ -212,14 +212,17 @@ float noise_wave(string wave, float a)
|
||||
|
||||
/* Turbulence */
|
||||
|
||||
float noise_turbulence(point p, string basis, int octaves, int hard)
|
||||
float noise_turbulence(point p, string basis, float details, int hard)
|
||||
{
|
||||
float fscale = 1.0;
|
||||
float amp = 1.0;
|
||||
float sum = 0.0;
|
||||
int i;
|
||||
int i, n;
|
||||
|
||||
float octaves = clamp(details, 0.0, 16.0);
|
||||
n = (int)octaves;
|
||||
|
||||
for (i = 0; i <= octaves; i++) {
|
||||
for (i = 0; i <= n; i++) {
|
||||
float t = noise_basis(fscale * p, basis);
|
||||
|
||||
if (hard)
|
||||
@@ -229,10 +232,26 @@ float noise_turbulence(point p, string basis, int octaves, int hard)
|
||||
amp *= 0.5;
|
||||
fscale *= 2.0;
|
||||
}
|
||||
|
||||
float rmd = octaves - floor(octaves);
|
||||
|
||||
sum *= ((float)(1 << octaves) / (float)((1 << (octaves + 1)) - 1));
|
||||
if(rmd != 0.0) {
|
||||
float t = noise_basis(fscale*p, basis);
|
||||
|
||||
return sum;
|
||||
if(hard)
|
||||
t = fabs(2.0*t - 1.0);
|
||||
|
||||
float sum2 = sum + t*amp;
|
||||
|
||||
sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1));
|
||||
sum2 *= ((float)(1 << (n+1))/(float)((1 << (n+2)) - 1));
|
||||
|
||||
return (1.0 - rmd)*sum + rmd*sum2;
|
||||
}
|
||||
else {
|
||||
sum *= ((float)(1 << n)/(float)((1 << (n+1)) - 1));
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
/* Utility */
|
||||
|
@@ -27,6 +27,6 @@ shader node_velvet_bsdf(
|
||||
{
|
||||
float sigma = clamp(Sigma, 0.0, 1.0);
|
||||
|
||||
BSDF = Color*ashikhmin_velvet(Normal, sigma);
|
||||
BSDF = Color*ashikhmin_velvet(Normal, sigma, 1.0);
|
||||
}
|
||||
|
||||
|
@@ -31,14 +31,14 @@ float wave(point p, float scale, string type, float detail, float distortion, fl
|
||||
float n = 0.0;
|
||||
|
||||
if(type == "Bands") {
|
||||
n = (x + y + z)*10.0);
|
||||
n = (x + y + z)*10.0;
|
||||
}
|
||||
else if(type == "Rings") {
|
||||
n = (sqrt(x*x + y*y + z*z)*20.0);
|
||||
}
|
||||
|
||||
if(distortion != 0.0) {
|
||||
n = n +(distortion * noise_turbulence(p*dscale, "Perlin", detail, 0);
|
||||
n = n +(distortion * noise_turbulence(p*dscale, "Perlin", detail, 0));
|
||||
}
|
||||
result = noise_wave("Sine", n);
|
||||
|
||||
@@ -48,12 +48,14 @@ float wave(point p, float scale, string type, float detail, float distortion, fl
|
||||
shader node_wave_texture(
|
||||
string Type = "Bands",
|
||||
float Scale = 5.0,
|
||||
float distortion = 0.0,
|
||||
float detail = 2.0,
|
||||
float dscale = 1.0,
|
||||
float Distortion = 0.0,
|
||||
float Detail = 2.0,
|
||||
float DetailScale = 1.0,
|
||||
point Vector = P,
|
||||
output float Fac = 0.0)
|
||||
output float Fac = 0.0,
|
||||
output color Color = color (0.0, 0.0, 0.0))
|
||||
{
|
||||
Fac = wave(Vector, Scale, Type, detail, distortion, dscale);
|
||||
Fac = wave(Vector, Scale, Type, Detail, Distortion, DetailScale);
|
||||
Color = color(Fac, Fac, Fac);
|
||||
}
|
||||
|
||||
|
91
intern/cycles/kernel/osl/nodes/oslutil.h
Normal file
91
intern/cycles/kernel/osl/nodes/oslutil.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Sony Pictures Imageworks nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef CCL_OSLUTIL_H
|
||||
#define CCL_OSLUTIL_H
|
||||
|
||||
// Return wireframe opacity factor [0, 1] given a geometry type in
|
||||
// ("triangles", "polygons" or "patches"), and a line_width in raster
|
||||
// or world space depending on the last (raster) boolean argument.
|
||||
//
|
||||
float wireframe(string edge_type, float line_width, int raster)
|
||||
{
|
||||
// ray differentials are so big in diffuse context that this function would always return "wire"
|
||||
if (raytype("path:diffuse")) return 0.0;
|
||||
|
||||
int np = 0;
|
||||
point p[64];
|
||||
float pixelWidth = 1;
|
||||
|
||||
if (edge_type == "triangles")
|
||||
{
|
||||
np = 3;
|
||||
if (!getattribute("geom:trianglevertices", p))
|
||||
return 0.0;
|
||||
}
|
||||
else if (edge_type == "polygons" || edge_type == "patches")
|
||||
{
|
||||
getattribute("geom:numpolyvertices", np);
|
||||
if (np < 3 || !getattribute("geom:polyvertices", p))
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (raster)
|
||||
{
|
||||
// Project the derivatives of P to the viewing plane defined
|
||||
// by I so we have a measure of how big is a pixel at this point
|
||||
float pixelWidthX = length(Dx(P) - dot(Dx(P), I) * I);
|
||||
float pixelWidthY = length(Dy(P) - dot(Dy(P), I) * I);
|
||||
// Take the average of both axis' length
|
||||
pixelWidth = (pixelWidthX + pixelWidthY) / 2;
|
||||
}
|
||||
|
||||
// Use half the width as the neighbor face will render the
|
||||
// other half. And take the square for fast comparison
|
||||
pixelWidth *= 0.5 * line_width;
|
||||
pixelWidth *= pixelWidth;
|
||||
for (int i = 0; i < np; i++)
|
||||
{
|
||||
int i2 = i ? i - 1 : np - 1;
|
||||
vector dir = P - p[i];
|
||||
vector edge = p[i] - p[i2];
|
||||
vector crs = cross(edge, dir);
|
||||
// At this point dot(crs, crs) / dot(edge, edge) is
|
||||
// the square of area / length(edge) == square of the
|
||||
// distance to the edge.
|
||||
if (dot(crs, crs) < (dot(edge, edge) * pixelWidth))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float wireframe(string edge_type, float line_width) { return wireframe(edge_type, line_width, 1); }
|
||||
float wireframe(string edge_type) { return wireframe(edge_type, 1.0, 1); }
|
||||
float wireframe() { return wireframe("polygons", 1.0, 1); }
|
||||
|
||||
#endif /* CCL_OSLUTIL_H */
|
@@ -35,6 +35,8 @@
|
||||
#define M_PI_2 1.5707963267948966 /* pi/2 */
|
||||
#define M_PI_4 0.7853981633974483 /* pi/4 */
|
||||
#define M_2_PI 0.6366197723675813 /* 2/pi */
|
||||
#define M_2PI 6.2831853071795865 /* 2*pi */
|
||||
#define M_4PI 12.566370614359173 /* 4*pi */
|
||||
#define M_2_SQRTPI 1.1283791670955126 /* 2/sqrt(pi) */
|
||||
#define M_E 2.7182818284590452 /* e (Euler's number) */
|
||||
#define M_LN2 0.6931471805599453 /* ln(2) */
|
||||
@@ -121,9 +123,16 @@ PERCOMP1 (round)
|
||||
PERCOMP1 (trunc)
|
||||
PERCOMP2 (fmod)
|
||||
PERCOMP2F (fmod)
|
||||
PERCOMP2 (mod)
|
||||
PERCOMP2F (mod)
|
||||
int mod (int x, int y) BUILTIN;
|
||||
int mod (int a, int b) { return a - b*(int)floor(a/b); }
|
||||
point mod (point a, point b) { return a - b*floor(a/b); }
|
||||
vector mod (vector a, vector b) { return a - b*floor(a/b); }
|
||||
normal mod (normal a, normal b) { return a - b*floor(a/b); }
|
||||
color mod (color a, color b) { return a - b*floor(a/b); }
|
||||
point mod (point a, float b) { return a - b*floor(a/b); }
|
||||
vector mod (vector a, float b) { return a - b*floor(a/b); }
|
||||
normal mod (normal a, float b) { return a - b*floor(a/b); }
|
||||
color mod (color a, float b) { return a - b*floor(a/b); }
|
||||
float mod (float a, float b) { return a - b*floor(a/b); }
|
||||
PERCOMP2 (min)
|
||||
PERCOMP2 (max)
|
||||
normal clamp (normal x, normal minval, normal maxval) { return max(min(x,maxval),minval); }
|
||||
@@ -131,11 +140,6 @@ vector clamp (vector x, vector minval, vector maxval) { return max(min(x,maxval)
|
||||
point clamp (point x, point minval, point maxval) { return max(min(x,maxval),minval); }
|
||||
color clamp (color x, color minval, color maxval) { return max(min(x,maxval),minval); }
|
||||
float clamp (float x, float minval, float maxval) { return max(min(x,maxval),minval); }
|
||||
//normal clamp (normal x, normal minval, normal maxval) BUILTIN;
|
||||
//vector clamp (vector x, vector minval, vector maxval) BUILTIN;
|
||||
//point clamp (point x, point minval, point maxval) BUILTIN;
|
||||
//color clamp (color x, color minval, color maxval) BUILTIN;
|
||||
//float clamp (float x, float minval, float maxval) BUILTIN;
|
||||
normal mix (normal x, normal y, normal a) { return x*(1-a) + y*a; }
|
||||
normal mix (normal x, normal y, float a) { return x*(1-a) + y*a; }
|
||||
vector mix (vector x, vector y, vector a) { return x*(1-a) + y*a; }
|
||||
@@ -163,246 +167,234 @@ vector normalize (vector v) BUILTIN;
|
||||
vector faceforward (vector N, vector I, vector Nref) BUILTIN;
|
||||
vector faceforward (vector N, vector I) BUILTIN;
|
||||
vector reflect (vector I, vector N) { return I - 2*dot(N,I)*N; }
|
||||
vector refract(vector I, vector N, float eta) {
|
||||
float IdotN = dot(I, N);
|
||||
float k = 1 - eta * eta * (1 - IdotN * IdotN);
|
||||
return (k < 0) ? vector(0, 0, 0) : (eta * I - N * (eta * IdotN + sqrt(k)));
|
||||
vector refract (vector I, vector N, float eta) {
|
||||
float IdotN = dot (I, N);
|
||||
float k = 1 - eta*eta * (1 - IdotN*IdotN);
|
||||
return (k < 0) ? vector(0,0,0) : (eta*I - N * (eta*IdotN + sqrt(k)));
|
||||
}
|
||||
void fresnel(vector I, normal N, float eta,
|
||||
output float Kr, output float Kt,
|
||||
output vector R, output vector T)
|
||||
void fresnel (vector I, normal N, float eta,
|
||||
output float Kr, output float Kt,
|
||||
output vector R, output vector T)
|
||||
{
|
||||
float sqr(float x) {
|
||||
return x * x;
|
||||
}
|
||||
float c = dot(I, N);
|
||||
if (c < 0)
|
||||
c = -c;
|
||||
R = reflect(I, N);
|
||||
float g = 1.0 / sqr(eta) - 1.0 + c * c;
|
||||
if (g >= 0.0) {
|
||||
g = sqrt(g);
|
||||
float beta = g - c;
|
||||
float F = (c * (g + c) - 1.0) / (c * beta + 1.0);
|
||||
F = 0.5 * (1.0 + sqr(F));
|
||||
F *= sqr(beta / (g + c));
|
||||
Kr = F;
|
||||
Kt = (1.0 - Kr) * eta * eta;
|
||||
// OPT: the following recomputes some of the above values, but it
|
||||
// gives us the same result as if the shader-writer called refract()
|
||||
T = refract(I, N, eta);
|
||||
}
|
||||
else {
|
||||
// total internal reflection
|
||||
Kr = 1.0;
|
||||
Kt = 0.0;
|
||||
T = vector(0, 0, 0);
|
||||
}
|
||||
#undef sqr
|
||||
float sqr(float x) { return x*x; }
|
||||
float c = dot(I, N);
|
||||
if (c < 0)
|
||||
c = -c;
|
||||
R = reflect(I, N);
|
||||
float g = 1.0 / sqr(eta) - 1.0 + c * c;
|
||||
if (g >= 0.0) {
|
||||
g = sqrt (g);
|
||||
float beta = g - c;
|
||||
float F = (c * (g+c) - 1.0) / (c * beta + 1.0);
|
||||
F = 0.5 * (1.0 + sqr(F));
|
||||
F *= sqr (beta / (g+c));
|
||||
Kr = F;
|
||||
Kt = (1.0 - Kr) * eta*eta;
|
||||
// OPT: the following recomputes some of the above values, but it
|
||||
// gives us the same result as if the shader-writer called refract()
|
||||
T = refract(I, N, eta);
|
||||
} else {
|
||||
// total internal reflection
|
||||
Kr = 1.0;
|
||||
Kt = 0.0;
|
||||
T = vector (0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
void fresnel(vector I, normal N, float eta,
|
||||
output float Kr, output float Kt)
|
||||
void fresnel (vector I, normal N, float eta,
|
||||
output float Kr, output float Kt)
|
||||
{
|
||||
vector R, T;
|
||||
fresnel(I, N, eta, Kr, Kt, R, T);
|
||||
vector R, T;
|
||||
fresnel(I, N, eta, Kr, Kt, R, T);
|
||||
}
|
||||
|
||||
point rotate(point q, float angle, point a, point b) BUILTIN;
|
||||
|
||||
normal transform(matrix Mto, normal p) BUILTIN;
|
||||
vector transform(matrix Mto, vector p) BUILTIN;
|
||||
point transform(matrix Mto, point p) BUILTIN;
|
||||
normal transform (matrix Mto, normal p) BUILTIN;
|
||||
vector transform (matrix Mto, vector p) BUILTIN;
|
||||
point transform (matrix Mto, point p) BUILTIN;
|
||||
normal transform (string from, string to, normal p) BUILTIN;
|
||||
vector transform (string from, string to, vector p) BUILTIN;
|
||||
point transform (string from, string to, point p) BUILTIN;
|
||||
normal transform (string to, normal p) { return transform("common",to,p); }
|
||||
vector transform (string to, vector p) { return transform("common",to,p); }
|
||||
point transform (string to, point p) { return transform("common",to,p); }
|
||||
|
||||
// Implementation of transform-with-named-space in terms of matrices:
|
||||
float transformu (string tounits, float x) BUILTIN;
|
||||
float transformu (string fromunits, string tounits, float x) BUILTIN;
|
||||
|
||||
point transform(string tospace, point x)
|
||||
point rotate (point p, float angle, point a, point b)
|
||||
{
|
||||
return transform(matrix("common", tospace), x);
|
||||
vector axis = normalize (b - a);
|
||||
float cosang, sinang;
|
||||
sincos (angle, sinang, cosang);
|
||||
float cosang1 = 1.0 - cosang;
|
||||
float x = axis[0], y = axis[1], z = axis[2];
|
||||
matrix M = matrix (x * x + (1.0 - x * x) * cosang,
|
||||
x * y * cosang1 + z * sinang,
|
||||
x * z * cosang1 - y * sinang,
|
||||
0.0,
|
||||
x * y * cosang1 - z * sinang,
|
||||
y * y + (1.0 - y * y) * cosang,
|
||||
y * z * cosang1 + x * sinang,
|
||||
0.0,
|
||||
x * z * cosang1 + y * sinang,
|
||||
y * z * cosang1 - x * sinang,
|
||||
z * z + (1.0 - z * z) * cosang,
|
||||
0.0,
|
||||
0.0, 0.0, 0.0, 1.0);
|
||||
return transform (M, p-a) + a;
|
||||
}
|
||||
|
||||
point transform(string fromspace, string tospace, point x)
|
||||
{
|
||||
return transform(matrix(fromspace, tospace), x);
|
||||
}
|
||||
|
||||
|
||||
vector transform(string tospace, vector x)
|
||||
{
|
||||
return transform(matrix("common", tospace), x);
|
||||
}
|
||||
|
||||
vector transform(string fromspace, string tospace, vector x)
|
||||
{
|
||||
return transform(matrix(fromspace, tospace), x);
|
||||
}
|
||||
|
||||
|
||||
normal transform(string tospace, normal x)
|
||||
{
|
||||
return transform(matrix("common", tospace), x);
|
||||
}
|
||||
|
||||
normal transform(string fromspace, string tospace, normal x)
|
||||
{
|
||||
return transform(matrix(fromspace, tospace), x);
|
||||
}
|
||||
|
||||
float transformu(string tounits, float x) BUILTIN;
|
||||
float transformu(string fromunits, string tounits, float x) BUILTIN;
|
||||
|
||||
|
||||
// Color functions
|
||||
|
||||
float luminance(color c) {
|
||||
return dot((vector)c, vector(0.2126, 0.7152, 0.0722));
|
||||
float luminance (color c) BUILTIN;
|
||||
color blackbody (float temperatureK) BUILTIN;
|
||||
color wavelength_color (float wavelength_nm) BUILTIN;
|
||||
|
||||
|
||||
color transformc (string to, color x)
|
||||
{
|
||||
color rgb_to_hsv (color rgb) { // See Foley & van Dam
|
||||
float r = rgb[0], g = rgb[1], b = rgb[2];
|
||||
float mincomp = min (r, min (g, b));
|
||||
float maxcomp = max (r, max (g, b));
|
||||
float delta = maxcomp - mincomp; // chroma
|
||||
float h, s, v;
|
||||
v = maxcomp;
|
||||
if (maxcomp > 0)
|
||||
s = delta / maxcomp;
|
||||
else s = 0;
|
||||
if (s <= 0)
|
||||
h = 0;
|
||||
else {
|
||||
if (r >= maxcomp) h = (g-b) / delta;
|
||||
else if (g >= maxcomp) h = 2 + (b-r) / delta;
|
||||
else h = 4 + (r-g) / delta;
|
||||
h /= 6;
|
||||
if (h < 0)
|
||||
h += 1;
|
||||
}
|
||||
return color (h, s, v);
|
||||
}
|
||||
|
||||
color rgb_to_hsl (color rgb) { // See Foley & van Dam
|
||||
// First convert rgb to hsv, then to hsl
|
||||
float minval = min (rgb[0], min (rgb[1], rgb[2]));
|
||||
color hsv = rgb_to_hsv (rgb);
|
||||
float maxval = hsv[2]; // v == maxval
|
||||
float h = hsv[0], s, l = (minval+maxval) / 2;
|
||||
if (minval == maxval)
|
||||
s = 0; // special 'achromatic' case, hue is 0
|
||||
else if (l <= 0.5)
|
||||
s = (maxval - minval) / (maxval + minval);
|
||||
else
|
||||
s = (maxval - minval) / (2 - maxval - minval);
|
||||
return color (h, s, l);
|
||||
}
|
||||
|
||||
color r;
|
||||
if (to == "rgb" || to == "RGB")
|
||||
r = x;
|
||||
else if (to == "hsv")
|
||||
r = rgb_to_hsv (x);
|
||||
else if (to == "hsl")
|
||||
r = rgb_to_hsl (x);
|
||||
else if (to == "YIQ")
|
||||
r = color (dot (vector(0.299, 0.587, 0.114), (vector)x),
|
||||
dot (vector(0.596, -0.275, -0.321), (vector)x),
|
||||
dot (vector(0.212, -0.523, 0.311), (vector)x));
|
||||
else if (to == "xyz")
|
||||
r = color (dot (vector(0.412453, 0.357580, 0.180423), (vector)x),
|
||||
dot (vector(0.212671, 0.715160, 0.072169), (vector)x),
|
||||
dot (vector(0.019334, 0.119193, 0.950227), (vector)x));
|
||||
else {
|
||||
error ("Unknown color space \"%s\"", to);
|
||||
r = x;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
color transformc(string to, color x)
|
||||
color transformc (string from, string to, color x)
|
||||
{
|
||||
color rgb_to_hsv(color rgb) { // See Foley & van Dam
|
||||
float r = rgb[0], g = rgb[1], b = rgb[2];
|
||||
float mincomp = min(r, min(g, b));
|
||||
float maxcomp = max(r, max(g, b));
|
||||
float delta = maxcomp - mincomp; // chroma
|
||||
float h, s, v;
|
||||
v = maxcomp;
|
||||
if (maxcomp > 0)
|
||||
s = delta / maxcomp;
|
||||
else s = 0;
|
||||
if (s <= 0)
|
||||
h = 0;
|
||||
else {
|
||||
if (r >= maxcomp) h = (g - b) / delta;
|
||||
else if (g >= maxcomp) h = 2 + (b - r) / delta;
|
||||
else h = 4 + (r - g) / delta;
|
||||
h /= 6;
|
||||
if (h < 0)
|
||||
h += 1;
|
||||
}
|
||||
return color(h, s, v);
|
||||
}
|
||||
color hsv_to_rgb (color c) { // Reference: Foley & van Dam
|
||||
float h = c[0], s = c[1], v = c[2];
|
||||
color r;
|
||||
if (s < 0.0001) {
|
||||
r = v;
|
||||
} else {
|
||||
h = 6 * (h - floor(h)); // expand to [0..6)
|
||||
int hi = (int)h;
|
||||
float f = h - hi;
|
||||
float p = v * (1-s);
|
||||
float q = v * (1-s*f);
|
||||
float t = v * (1-s*(1-f));
|
||||
if (hi == 0) r = color (v, t, p);
|
||||
else if (hi == 1) r = color (q, v, p);
|
||||
else if (hi == 2) r = color (p, v, t);
|
||||
else if (hi == 3) r = color (p, q, v);
|
||||
else if (hi == 4) r = color (t, p, v);
|
||||
else r = color (v, p, q);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
color rgb_to_hsl(color rgb) { // See Foley & van Dam
|
||||
// First convert rgb to hsv, then to hsl
|
||||
float minval = min(rgb[0], min(rgb[1], rgb[2]));
|
||||
color hsv = rgb_to_hsv(rgb);
|
||||
float maxval = hsv[2]; // v == maxval
|
||||
float h = hsv[0], s, l = (minval + maxval) / 2;
|
||||
if (minval == maxval)
|
||||
s = 0; // special 'achromatic' case, hue is 0
|
||||
else if (l <= 0.5)
|
||||
s = (maxval - minval) / (maxval + minval);
|
||||
else
|
||||
s = (maxval - minval) / (2 - maxval - minval);
|
||||
return color(h, s, l);
|
||||
}
|
||||
color hsl_to_rgb (color c) {
|
||||
float h = c[0], s = c[1], l = c[2];
|
||||
// Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
|
||||
float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
|
||||
color r;
|
||||
if (v <= 0) {
|
||||
r = 0;
|
||||
} else {
|
||||
float min = 2 * l - v;
|
||||
s = (v - min) / v;
|
||||
r = hsv_to_rgb (color (h, s, v));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
color r;
|
||||
if (to == "rgb" || to == "RGB")
|
||||
r = x;
|
||||
else if (to == "hsv")
|
||||
r = rgb_to_hsv(x);
|
||||
else if (to == "hsl")
|
||||
r = rgb_to_hsl(x);
|
||||
else if (to == "YIQ")
|
||||
r = color(dot(vector(0.299, 0.587, 0.114), (vector)x),
|
||||
dot(vector(0.596, -0.275, -0.321), (vector)x),
|
||||
dot(vector(0.212, -0.523, 0.311), (vector)x));
|
||||
else if (to == "xyz")
|
||||
r = color(dot(vector(0.412453, 0.357580, 0.180423), (vector)x),
|
||||
dot(vector(0.212671, 0.715160, 0.072169), (vector)x),
|
||||
dot(vector(0.019334, 0.119193, 0.950227), (vector)x));
|
||||
else {
|
||||
error("Unknown color space \"%s\"", to);
|
||||
r = x;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
color transformc(string from, string to, color x)
|
||||
{
|
||||
color hsv_to_rgb(color c) { // Reference: Foley & van Dam
|
||||
float h = c[0], s = c[1], v = c[2];
|
||||
color r;
|
||||
if (s < 0.0001) {
|
||||
r = v;
|
||||
}
|
||||
else {
|
||||
h = 6 * (h - floor(h)); // expand to [0..6)
|
||||
int hi = (int)h;
|
||||
float f = h - hi;
|
||||
float p = v * (1 - s);
|
||||
float q = v * (1 - s * f);
|
||||
float t = v * (1 - s * (1 - f));
|
||||
if (hi == 0) r = color(v, t, p);
|
||||
else if (hi == 1) r = color(q, v, p);
|
||||
else if (hi == 2) r = color(p, v, t);
|
||||
else if (hi == 3) r = color(p, q, v);
|
||||
else if (hi == 4) r = color(t, p, v);
|
||||
else r = color(v, p, q);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
color hsl_to_rgb(color c) {
|
||||
float h = c[0], s = c[1], l = c[2];
|
||||
// Easiest to convert hsl -> hsv, then hsv -> RGB (per Foley & van Dam)
|
||||
float v = (l <= 0.5) ? (l * (1 + s)) : (l * (1 - s) + s);
|
||||
color r;
|
||||
if (v <= 0) {
|
||||
r = 0;
|
||||
}
|
||||
else {
|
||||
float min = 2 * l - v;
|
||||
s = (v - min) / v;
|
||||
r = hsv_to_rgb(color(h, s, v));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
color r;
|
||||
if (from == "rgb" || from == "RGB")
|
||||
r = x;
|
||||
else if (from == "hsv")
|
||||
r = hsv_to_rgb(x);
|
||||
else if (from == "hsl")
|
||||
r = hsl_to_rgb(x);
|
||||
else if (from == "YIQ")
|
||||
r = color(dot(vector(1, 0.9557, 0.6199), (vector)x),
|
||||
dot(vector(1, -0.2716, -0.6469), (vector)x),
|
||||
dot(vector(1, -1.1082, 1.7051), (vector)x));
|
||||
else if (from == "xyz")
|
||||
r = color(dot(vector(3.240479, -1.537150, -0.498535), (vector)x),
|
||||
dot(vector(-0.969256, 1.875991, 0.041556), (vector)x),
|
||||
dot(vector(0.055648, -0.204043, 1.057311), (vector)x));
|
||||
else {
|
||||
error("Unknown color space \"%s\"", to);
|
||||
r = x;
|
||||
}
|
||||
return transformc(to, r);
|
||||
color r;
|
||||
if (from == "rgb" || from == "RGB")
|
||||
r = x;
|
||||
else if (from == "hsv")
|
||||
r = hsv_to_rgb (x);
|
||||
else if (from == "hsl")
|
||||
r = hsl_to_rgb (x);
|
||||
else if (from == "YIQ")
|
||||
r = color (dot (vector(1, 0.9557, 0.6199), (vector)x),
|
||||
dot (vector(1, -0.2716, -0.6469), (vector)x),
|
||||
dot (vector(1, -1.1082, 1.7051), (vector)x));
|
||||
else if (from == "xyz")
|
||||
r = color (dot (vector( 3.240479, -1.537150, -0.498535), (vector)x),
|
||||
dot (vector(-0.969256, 1.875991, 0.041556), (vector)x),
|
||||
dot (vector( 0.055648, -0.204043, 1.057311), (vector)x));
|
||||
else {
|
||||
error ("Unknown color space \"%s\"", to);
|
||||
r = x;
|
||||
}
|
||||
return transformc (to, r);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Matrix functions
|
||||
|
||||
float determinant(matrix m) BUILTIN;
|
||||
matrix transpose(matrix m) BUILTIN;
|
||||
float determinant (matrix m) BUILTIN;
|
||||
matrix transpose (matrix m) BUILTIN;
|
||||
|
||||
|
||||
|
||||
// Pattern generation
|
||||
|
||||
float step(float edge, float x) BUILTIN;
|
||||
color step(color edge, color x) BUILTIN;
|
||||
point step(point edge, point x) BUILTIN;
|
||||
vector step(vector edge, vector x) BUILTIN;
|
||||
normal step(normal edge, normal x) BUILTIN;
|
||||
float smoothstep(float edge0, float edge1, float x) BUILTIN;
|
||||
float step (float edge, float x) BUILTIN;
|
||||
color step (color edge, color x) BUILTIN;
|
||||
point step (point edge, point x) BUILTIN;
|
||||
vector step (vector edge, vector x) BUILTIN;
|
||||
normal step (normal edge, normal x) BUILTIN;
|
||||
float smoothstep (float edge0, float edge1, float x) BUILTIN;
|
||||
|
||||
|
||||
// Derivatives and area operators
|
||||
@@ -413,26 +405,24 @@ float smoothstep(float edge0, float edge1, float x) BUILTIN;
|
||||
|
||||
// String functions
|
||||
|
||||
int strlen(string s) BUILTIN;
|
||||
int startswith(string s, string prefix) BUILTIN;
|
||||
int endswith(string s, string suffix) BUILTIN;
|
||||
string substr(string s, int start, int len) BUILTIN;
|
||||
string substr(string s, int start) {
|
||||
return substr(s, start, strlen(s));
|
||||
}
|
||||
int strlen (string s) BUILTIN;
|
||||
int startswith (string s, string prefix) BUILTIN;
|
||||
int endswith (string s, string suffix) BUILTIN;
|
||||
string substr (string s, int start, int len) BUILTIN;
|
||||
string substr (string s, int start) { return substr (s, start, strlen(s)); }
|
||||
|
||||
// Define concat in terms of shorter concat
|
||||
string concat(string a, string b, string c) {
|
||||
return concat(concat(a, b), c);
|
||||
string concat (string a, string b, string c) {
|
||||
return concat(concat(a,b), c);
|
||||
}
|
||||
string concat(string a, string b, string c, string d) {
|
||||
return concat(concat(a, b, c), d);
|
||||
string concat (string a, string b, string c, string d) {
|
||||
return concat(concat(a,b,c), d);
|
||||
}
|
||||
string concat(string a, string b, string c, string d, string e) {
|
||||
return concat(concat(a, b, c, d), e);
|
||||
string concat (string a, string b, string c, string d, string e) {
|
||||
return concat(concat(a,b,c,d), e);
|
||||
}
|
||||
string concat(string a, string b, string c, string d, string e, string f) {
|
||||
return concat(concat(a, b, c, d, e), f);
|
||||
string concat (string a, string b, string c, string d, string e, string f) {
|
||||
return concat(concat(a,b,c,d,e), f);
|
||||
}
|
||||
|
||||
|
||||
@@ -445,16 +435,20 @@ closure color diffuse(normal N) BUILTIN;
|
||||
closure color oren_nayar(normal N, float sigma) BUILTIN;
|
||||
closure color translucent(normal N) BUILTIN;
|
||||
closure color reflection(normal N, float eta) BUILTIN;
|
||||
closure color reflection(normal N) { return reflection(N, 0.0); }
|
||||
closure color reflection(normal N) { return reflection (N, 0.0); }
|
||||
closure color refraction(normal N, float eta) BUILTIN;
|
||||
closure color dielectric(normal N, float eta) BUILTIN;
|
||||
closure color transparent() BUILTIN;
|
||||
closure color microfacet_ggx(normal N, float ag) BUILTIN;
|
||||
closure color microfacet_ggx(normal N, float ag, float eta) BUILTIN;
|
||||
closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
|
||||
closure color microfacet_beckmann(normal N, float ab) BUILTIN;
|
||||
closure color microfacet_beckmann(normal N, float ab, float eta) BUILTIN;
|
||||
closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN;
|
||||
closure color ward(normal N, vector T, float ax, float ay) BUILTIN;
|
||||
closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
|
||||
closure color ward(normal N, vector T,float ax, float ay) BUILTIN;
|
||||
closure color phong(normal N, float exponent) BUILTIN;
|
||||
closure color phong_ramp(normal N, float exponent, color colors[8]) BUILTIN;
|
||||
closure color hair_diffuse(vector T) BUILTIN;
|
||||
closure color hair_specular(vector T, float offset, float exponent) BUILTIN;
|
||||
closure color ashikhmin_velvet(normal N, float sigma, float eta) BUILTIN;
|
||||
closure color westin_backscatter(normal N, float roughness) BUILTIN;
|
||||
closure color westin_sheen(normal N, float edginess) BUILTIN;
|
||||
closure color bssrdf_cubic(color radius) BUILTIN;
|
||||
@@ -464,10 +458,75 @@ closure color emission() BUILTIN;
|
||||
closure color debug(string tag) BUILTIN;
|
||||
closure color background() BUILTIN;
|
||||
closure color holdout() BUILTIN;
|
||||
closure color subsurface(float eta, float g, float mfp, float albedo) BUILTIN;
|
||||
closure color subsurface(float eta, float g, color mfp, color albedo) BUILTIN;
|
||||
|
||||
closure color cloth(normal N, float s, float t, float dsdx, float dtdx, float dsdy, float dtdy,
|
||||
float area_scaled, vector dPdu, color diff_warp_col, color diff_weft_col,
|
||||
color spec_warp_col, color spec_weft_col, float fresnel_warp, float fresnel_weft,
|
||||
float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle,
|
||||
float warp_width_scale, float weft_width_scale, float thread_count_mult_u,
|
||||
float thread_count_mult_v) BUILTIN;
|
||||
closure color cloth_specular(normal N, color spec_col[4], float eta[4], int thread_pattern[4],
|
||||
float pattern_weight[4], int current_thread, float brdf_interp,
|
||||
float btf_interp, float uux, float vvx, float area_scaled, vector dPdu,
|
||||
float eccentricity[4], float angle[4], float Kx[4], float Ky[4],
|
||||
float Sx[4], float Sy[4]) BUILTIN;
|
||||
closure color fakefur_diffuse(normal N, vector T, float fur_reflectivity, float fur_transmission,
|
||||
float shadow_start, float shadow_end, float fur_attenuation, float fur_density,
|
||||
float fur_avg_radius, float fur_length, float fur_shadow_fraction) BUILTIN;
|
||||
closure color fakefur_specular(normal N, vector T, float offset, float exp, float fur_reflectivity,
|
||||
float fur_transmission, float shadow_start, float shadow_end,
|
||||
float fur_attenuation, float fur_density, float fur_avg_radius,
|
||||
float fur_length, float fur_shadow_fraction) BUILTIN;
|
||||
|
||||
closure color fakefur_skin(vector N, vector T, float fur_reflectivity, float fur_transmission,
|
||||
float shadow_start, float shadow_end, float fur_attenuation, float fur_density,
|
||||
float fur_avg_radius, float fur_length) BUILTIN;
|
||||
|
||||
|
||||
closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft,
|
||||
color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft,
|
||||
float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle,
|
||||
float warp_width_scale, float weft_width_scale, float thread_count_mult_u,
|
||||
float thread_count_mult_v)
|
||||
{
|
||||
|
||||
return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft,
|
||||
fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle,
|
||||
warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v);
|
||||
}
|
||||
|
||||
closure color cloth(normal N, float s, float t, color diff_warp, color diff_weft,
|
||||
color spec_warp, color spec_weft, float fresnel_warp, float fresnel_weft,
|
||||
float spread_x_mult, float spread_y_mult, int pattern, float pattern_angle,
|
||||
float warp_width_scale, float weft_width_scale, float thread_count_mult_u,
|
||||
float thread_count_mult_v, string tok, string val)
|
||||
{
|
||||
|
||||
return cloth(N, s, t, Dx(s), Dx(t), Dy(s), Dy(t), area(P), dPdu, diff_warp, diff_weft, spec_warp, spec_weft,
|
||||
fresnel_warp, fresnel_weft, spread_x_mult, spread_y_mult, pattern, pattern_angle,
|
||||
warp_width_scale, weft_width_scale, thread_count_mult_u, thread_count_mult_v, tok, val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Renderer state
|
||||
int raytype(string typename) BUILTIN;
|
||||
int raytype (string typename) BUILTIN;
|
||||
// the individual 'isFOOray' functions are deprecated
|
||||
int iscameraray () { return raytype("camera"); }
|
||||
int isdiffuseray () { return raytype("diffuse"); }
|
||||
int isglossyray () { return raytype("glossy"); }
|
||||
int isshadowray () { return raytype("shadow"); }
|
||||
int getmatrix (string fromspace, string tospace, output matrix M) BUILTIN;
|
||||
int getmatrix (string fromspace, output matrix M) {
|
||||
return getmatrix (fromspace, "common", M);
|
||||
}
|
||||
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
|
||||
|
||||
|
||||
#undef BUILTIN
|
||||
#undef BUILTIN_DERIV
|
||||
@@ -476,4 +535,3 @@ int raytype(string typename) BUILTIN;
|
||||
#undef PERCOMP2F
|
||||
|
||||
#endif /* CCL_STDOSL_H */
|
||||
|
||||
|
@@ -75,6 +75,8 @@ void OSLShader::register_closures(OSL::ShadingSystem *ss)
|
||||
register_closure(ss, "microfacet_beckmann", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID, bsdf_microfacet_beckmann_params, bsdf_microfacet_beckmann_prepare);
|
||||
register_closure(ss, "microfacet_beckmann_refraction", OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, bsdf_microfacet_beckmann_refraction_params, bsdf_microfacet_beckmann_refraction_prepare);
|
||||
register_closure(ss, "ward", OSL_CLOSURE_BSDF_WARD_ID, bsdf_ward_params, bsdf_ward_prepare);
|
||||
register_closure(ss, "phong", OSL_CLOSURE_BSDF_PHONG_ID, bsdf_phong_params, bsdf_phong_prepare);
|
||||
register_closure(ss, "phong_ramp", OSL_CLOSURE_BSDF_PHONG_RAMP_ID, bsdf_phong_ramp_params, bsdf_phong_ramp_prepare);
|
||||
register_closure(ss, "ashikhmin_velvet", OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID, bsdf_ashikhmin_velvet_params, bsdf_ashikhmin_velvet_prepare);
|
||||
register_closure(ss, "westin_backscatter", OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID, bsdf_westin_backscatter_params, bsdf_westin_backscatter_prepare);
|
||||
register_closure(ss, "westin_sheen", OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID, bsdf_westin_sheen_params, bsdf_westin_sheen_prepare);
|
||||
|
@@ -51,6 +51,8 @@ enum {
|
||||
OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
|
||||
OSL_CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
|
||||
OSL_CLOSURE_BSDF_WARD_ID,
|
||||
OSL_CLOSURE_BSDF_PHONG_ID,
|
||||
OSL_CLOSURE_BSDF_PHONG_RAMP_ID,
|
||||
OSL_CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
|
||||
OSL_CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
|
||||
OSL_CLOSURE_BSDF_WESTIN_SHEEN_ID,
|
||||
@@ -73,6 +75,8 @@ extern OSL::ClosureParam bsdf_microfacet_ggx_refraction_params[];
|
||||
extern OSL::ClosureParam bsdf_microfacet_beckmann_params[];
|
||||
extern OSL::ClosureParam bsdf_microfacet_beckmann_refraction_params[];
|
||||
extern OSL::ClosureParam bsdf_ward_params[];
|
||||
extern OSL::ClosureParam bsdf_phong_params[];
|
||||
extern OSL::ClosureParam bsdf_phong_ramp_params[];
|
||||
extern OSL::ClosureParam bsdf_ashikhmin_velvet_params[];
|
||||
extern OSL::ClosureParam bsdf_westin_backscatter_params[];
|
||||
extern OSL::ClosureParam bsdf_westin_sheen_params[];
|
||||
@@ -94,6 +98,8 @@ void bsdf_microfacet_ggx_refraction_prepare(OSL::RendererServices *, int id, voi
|
||||
void bsdf_microfacet_beckmann_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void bsdf_microfacet_beckmann_refraction_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void bsdf_ward_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void bsdf_phong_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void bsdf_ashikhmin_velvet_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void bsdf_westin_backscatter_prepare(OSL::RendererServices *, int id, void *data);
|
||||
void bsdf_westin_sheen_prepare(OSL::RendererServices *, int id, void *data);
|
||||
|
@@ -30,12 +30,15 @@
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class OSLRenderServices;
|
||||
|
||||
struct OSLGlobals {
|
||||
/* use */
|
||||
bool use;
|
||||
|
||||
/* shading system */
|
||||
/* shading system */
|
||||
OSL::ShadingSystem *ss;
|
||||
OSLRenderServices *services;
|
||||
|
||||
/* shader states */
|
||||
vector<OSL::ShadingAttribStateRef> surface_state;
|
||||
@@ -60,7 +63,7 @@ struct OSLGlobals {
|
||||
/* thread key for thread specific data lookup */
|
||||
struct ThreadData {
|
||||
OSL::ShaderGlobals globals;
|
||||
void *thread_info;
|
||||
OSL::PerThreadInfo *thread_info;
|
||||
};
|
||||
|
||||
static tls_ptr(ThreadData, thread_data);
|
||||
|
@@ -160,6 +160,18 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform)
|
||||
{
|
||||
// XXX implementation
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from)
|
||||
{
|
||||
// XXX implementation
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives,
|
||||
ustring object, TypeDesc type, ustring name,
|
||||
int index, void *val)
|
||||
@@ -167,55 +179,68 @@ bool OSLRenderServices::get_array_attribute(void *renderstate, bool derivatives,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd,
|
||||
const OSLGlobals::Attribute& attr, bool derivatives, void *val)
|
||||
static void set_attribute_float3(float3 f[3], TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
if (attr.type == TypeDesc::TypeFloat) {
|
||||
float *fval = (float *)val;
|
||||
fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
|
||||
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
||||
if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
|
||||
type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
|
||||
{
|
||||
float3 *fval = (float3 *)val;
|
||||
fval[0] = f[0];
|
||||
if (derivatives) {
|
||||
fval[1] = f[1];
|
||||
fval[2] = f[2];
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* todo: this won't work when float3 has w component */
|
||||
float3 *fval = (float3 *)val;
|
||||
fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
|
||||
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
||||
float *fval = (float *)val;
|
||||
fval[0] = average(f[0]);
|
||||
if (derivatives) {
|
||||
fval[1] = average(f[1]);
|
||||
fval[2] = average(f[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool get_mesh_attribute_convert(KernelGlobals *kg, const ShaderData *sd,
|
||||
const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val)
|
||||
static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
if (type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
|
||||
type == TypeDesc::TypeNormal || type == TypeDesc::TypeColor)
|
||||
{
|
||||
float3 *fval = (float3 *)val;
|
||||
fval[0] = make_float3(f[0], f[0], f[0]);
|
||||
if (derivatives) {
|
||||
fval[1] = make_float3(f[1], f[2], f[1]);
|
||||
fval[2] = make_float3(f[2], f[2], f[2]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
float *fval = (float *)val;
|
||||
fval[0] = f[0];
|
||||
if (derivatives) {
|
||||
fval[1] = f[1];
|
||||
fval[2] = f[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
|
||||
const TypeDesc& type, bool derivatives, void *val)
|
||||
{
|
||||
if (attr.type == TypeDesc::TypeFloat) {
|
||||
float tmp[3];
|
||||
float3 *fval = (float3 *)val;
|
||||
|
||||
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
|
||||
|
||||
fval[0] = make_float3(tmp[0], tmp[0], tmp[0]);
|
||||
if (derivatives) {
|
||||
fval[1] = make_float3(tmp[1], tmp[1], tmp[1]);
|
||||
fval[2] = make_float3(tmp[2], tmp[2], tmp[2]);
|
||||
}
|
||||
|
||||
float fval[3];
|
||||
fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset,
|
||||
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector ||
|
||||
attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor)
|
||||
{
|
||||
float3 tmp[3];
|
||||
float *fval = (float *)val;
|
||||
|
||||
get_mesh_attribute(kg, sd, attr, derivatives, tmp);
|
||||
|
||||
fval[0] = average(tmp[0]);
|
||||
if (derivatives) {
|
||||
fval[1] = average(tmp[1]);
|
||||
fval[2] = average(tmp[2]);
|
||||
}
|
||||
|
||||
/* todo: this won't work when float3 has w component */
|
||||
float3 fval[3];
|
||||
fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset,
|
||||
(derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL);
|
||||
set_attribute_float3(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -231,11 +256,116 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat
|
||||
memset((char *)val + datasize, 0, datasize * 2);
|
||||
}
|
||||
|
||||
static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
|
||||
TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
/* Object Attributes */
|
||||
if (name == "std::object_location") {
|
||||
float3 fval[3];
|
||||
fval[0] = object_location(kg, sd);
|
||||
fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */
|
||||
set_attribute_float3(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::object_index") {
|
||||
float fval[3];
|
||||
fval[0] = object_pass_id(kg, sd->object);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::material_index") {
|
||||
float fval[3];
|
||||
fval[0] = shader_pass_id(kg, sd);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::object_random") {
|
||||
float fval[3];
|
||||
fval[0] = object_random_number(kg, sd->object);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Particle Attributes */
|
||||
else if (name == "std::particle_index") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_index(kg, particle_id);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_age") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_age(kg, particle_id);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_lifetime") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_lifetime(kg, particle_id);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_location") {
|
||||
float3 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_location(kg, particle_id);
|
||||
fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */
|
||||
set_attribute_float3(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
#if 0 /* unsupported */
|
||||
else if (name == "std::particle_rotation") {
|
||||
float4 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_rotation(kg, particle_id);
|
||||
fval[1] = fval[2] = make_float4(0.0, 0.0, 0.0, 0.0); /* derivates set to 0 */
|
||||
set_attribute_float4(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
else if (name == "std::particle_size") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_size(kg, particle_id);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_velocity") {
|
||||
float3 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_velocity(kg, particle_id);
|
||||
fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */
|
||||
set_attribute_float3(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_angular_velocity") {
|
||||
float3 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_angular_velocity(kg, particle_id);
|
||||
fval[1] = fval[2] = make_float3(0.0, 0.0, 0.0); /* derivates set to 0 */
|
||||
set_attribute_float3(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustring object_name,
|
||||
TypeDesc type, ustring name, void *val)
|
||||
{
|
||||
KernelGlobals *kg = kernel_globals;
|
||||
const ShaderData *sd = (const ShaderData *)renderstate;
|
||||
ShaderData *sd = (ShaderData *)renderstate;
|
||||
int object = sd->object;
|
||||
int tri = sd->prim;
|
||||
|
||||
@@ -258,29 +388,23 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri
|
||||
OSLGlobals::AttributeMap& attribute_map = kg->osl.attribute_map[object];
|
||||
OSLGlobals::AttributeMap::iterator it = attribute_map.find(name);
|
||||
|
||||
if (it == attribute_map.end())
|
||||
return false;
|
||||
|
||||
/* type mistmatch? */
|
||||
const OSLGlobals::Attribute& attr = it->second;
|
||||
|
||||
if (attr.elem != ATTR_ELEMENT_VALUE) {
|
||||
/* triangle and vertex attributes */
|
||||
if (tri != ~0) {
|
||||
if (attr.type == type || (attr.type == TypeDesc::TypeColor &&
|
||||
(type == TypeDesc::TypePoint || type == TypeDesc::TypeVector || type == TypeDesc::TypeNormal)))
|
||||
{
|
||||
return get_mesh_attribute(kg, sd, attr, derivatives, val);
|
||||
}
|
||||
else {
|
||||
return get_mesh_attribute_convert(kg, sd, attr, type, derivatives, val);
|
||||
}
|
||||
if (it != attribute_map.end()) {
|
||||
const OSLGlobals::Attribute& attr = it->second;
|
||||
|
||||
if (attr.elem != ATTR_ELEMENT_VALUE) {
|
||||
/* triangle and vertex attributes */
|
||||
if (tri != ~0)
|
||||
return get_mesh_attribute(kg, sd, attr, type, derivatives, val);
|
||||
}
|
||||
else {
|
||||
/* object attribute */
|
||||
get_object_attribute(attr, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* object attribute */
|
||||
get_object_attribute(attr, derivatives, val);
|
||||
return true;
|
||||
/* not found in attribute, check standard object info */
|
||||
return get_object_standard_attribute(kg, sd, name, type, derivatives, val);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -297,137 +421,17 @@ bool OSLRenderServices::has_userdata(ustring name, TypeDesc type, void *renderst
|
||||
return false; /* never called by OSL */
|
||||
}
|
||||
|
||||
void *OSLRenderServices::get_pointcloud_attr_query(ustring *attr_names,
|
||||
TypeDesc *attr_types, int nattrs)
|
||||
int OSLRenderServices::pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er,
|
||||
float radius, int max_points, bool sort,
|
||||
size_t *out_indices, float *out_distances, int derivs_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OSLRenderServices::pointcloud_get(ustring filename, size_t *indices, int count,
|
||||
ustring attr_name, TypeDesc attr_type, void *out_data)
|
||||
{
|
||||
#ifdef WITH_PARTIO
|
||||
m_attr_queries.push_back(AttrQuery());
|
||||
AttrQuery &query = m_attr_queries.back();
|
||||
|
||||
/* make space for what we need. the only reason to use
|
||||
* std::vector is to skip the delete */
|
||||
query.attr_names.resize(nattrs);
|
||||
query.attr_partio_types.resize(nattrs);
|
||||
/* capacity will keep the length of the smallest array passed
|
||||
* to the query. Just to prevent buffer overruns */
|
||||
query.capacity = -1;
|
||||
|
||||
for (int i = 0; i < nattrs; ++i) {
|
||||
query.attr_names[i] = attr_names[i];
|
||||
|
||||
TypeDesc element_type = attr_types[i].elementtype();
|
||||
|
||||
if (query.capacity < 0)
|
||||
query.capacity = attr_types[i].numelements();
|
||||
else
|
||||
query.capacity = min(query.capacity, (int)attr_types[i].numelements());
|
||||
|
||||
/* convert the OSL (OIIO) type to the equivalent Partio type so
|
||||
* we can do a fast check at query time. */
|
||||
if (element_type == TypeDesc::TypeFloat) {
|
||||
query.attr_partio_types[i] = Partio::FLOAT;
|
||||
}
|
||||
else if (element_type == TypeDesc::TypeInt) {
|
||||
query.attr_partio_types[i] = Partio::INT;
|
||||
}
|
||||
else if (element_type == TypeDesc::TypeColor || element_type == TypeDesc::TypePoint ||
|
||||
element_type == TypeDesc::TypeVector || element_type == TypeDesc::TypeNormal)
|
||||
{
|
||||
query.attr_partio_types[i] = Partio::VECTOR;
|
||||
}
|
||||
else {
|
||||
return NULL; /* report some error of unknown type */
|
||||
}
|
||||
}
|
||||
|
||||
/* this is valid until the end of RenderServices */
|
||||
return &query;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WITH_PARTIO
|
||||
Partio::ParticlesData *OSLRenderServices::get_pointcloud(ustring filename)
|
||||
{
|
||||
return Partio::readCached(filename.c_str(), true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int OSLRenderServices::pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius,
|
||||
int max_points, void *_attr_query, void **attr_outdata)
|
||||
{
|
||||
/* todo: this code has never been tested, and most likely does not
|
||||
* work. it's based on the example code in OSL */
|
||||
|
||||
#ifdef WITH_PARTIO
|
||||
/* query Partio for this pointcloud lookup using cached attr_query */
|
||||
if (!_attr_query)
|
||||
return 0;
|
||||
|
||||
AttrQuery *attr_query = (AttrQuery *)_attr_query;
|
||||
if (attr_query->capacity < max_points)
|
||||
return 0;
|
||||
|
||||
/* get the pointcloud entry for the given filename */
|
||||
Partio::ParticlesData *cloud = get_pointcloud(filename);
|
||||
|
||||
/* now we have to look up all the attributes in the file. we can't do this
|
||||
* before hand cause we never know what we are going to load. */
|
||||
int nattrs = attr_query->attr_names.size();
|
||||
Partio::ParticleAttribute *attr = (Partio::ParticleAttribute *)alloca(sizeof(Partio::ParticleAttribute) * nattrs);
|
||||
|
||||
for (int i = 0; i < nattrs; ++i) {
|
||||
/* special case attributes */
|
||||
if (attr_query->attr_names[i] == u_distance || attr_query->attr_names[i] == u_index)
|
||||
continue;
|
||||
|
||||
/* lookup the attribute by name*/
|
||||
if (!cloud->attributeInfo(attr_query->attr_names[i].c_str(), attr[i])) {
|
||||
/* issue an error here and return, types don't match */
|
||||
Partio::endCachedAccess(cloud);
|
||||
cloud->release();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Partio::ParticleIndex> indices;
|
||||
std::vector<float> dist2;
|
||||
|
||||
Partio::beginCachedAccess(cloud);
|
||||
|
||||
/* finally, do the lookup */
|
||||
cloud->findNPoints((const float *)¢er, max_points, radius, indices, dist2);
|
||||
int count = indices.size();
|
||||
|
||||
/* retrieve the attributes directly to user space */
|
||||
for (int j = 0; j < nattrs; ++j) {
|
||||
/* special cases */
|
||||
if (attr_query->attr_names[j] == u_distance) {
|
||||
for (int i = 0; i < count; ++i)
|
||||
((float *)attr_outdata[j])[i] = sqrtf(dist2[i]);
|
||||
}
|
||||
else if (attr_query->attr_names[j] == u_index) {
|
||||
for (int i = 0; i < count; ++i)
|
||||
((int *)attr_outdata[j])[i] = indices[i];
|
||||
}
|
||||
else {
|
||||
/* note we make a single call per attribute, we don't loop over the
|
||||
* points. Partio does it, so it is there that we have to care about
|
||||
* performance */
|
||||
cloud->data(attr[j], count, &indices[0], true, attr_outdata[j]);
|
||||
}
|
||||
}
|
||||
|
||||
Partio::endCachedAccess(cloud);
|
||||
cloud->release();
|
||||
|
||||
return count;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@@ -30,18 +30,14 @@
|
||||
#include <OSL/oslexec.h>
|
||||
#include <OSL/oslclosure.h>
|
||||
|
||||
#ifdef WITH_PARTIO
|
||||
#include <Partio.h>
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
class Object;
|
||||
class Scene;
|
||||
class Shader;
|
||||
class ShaderData;
|
||||
class float3;
|
||||
class KernelGlobals;
|
||||
struct ShaderData;
|
||||
struct float3;
|
||||
struct KernelGlobals;
|
||||
|
||||
class OSLRenderServices : public OSL::RendererServices
|
||||
{
|
||||
@@ -53,48 +49,33 @@ public:
|
||||
|
||||
bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
|
||||
bool get_inverse_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform, float time);
|
||||
|
||||
bool get_matrix(OSL::Matrix44 &result, ustring from, float time);
|
||||
bool get_inverse_matrix(OSL::Matrix44 &result, ustring to, float time);
|
||||
|
||||
bool get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr xform);
|
||||
bool get_matrix(OSL::Matrix44 &result, ustring from);
|
||||
|
||||
bool get_array_attribute(void *renderstate, bool derivatives,
|
||||
bool get_array_attribute(void *renderstate, bool derivatives,
|
||||
ustring object, TypeDesc type, ustring name,
|
||||
int index, void *val);
|
||||
bool get_attribute(void *renderstate, bool derivatives, ustring object,
|
||||
TypeDesc type, ustring name, void *val);
|
||||
|
||||
bool get_userdata(bool derivatives, ustring name, TypeDesc type,
|
||||
bool get_userdata(bool derivatives, ustring name, TypeDesc type,
|
||||
void *renderstate, void *val);
|
||||
bool has_userdata(ustring name, TypeDesc type, void *renderstate);
|
||||
|
||||
void *get_pointcloud_attr_query(ustring *attr_names,
|
||||
TypeDesc *attr_types, int nattrs);
|
||||
int pointcloud(ustring filename, const OSL::Vec3 ¢er, float radius,
|
||||
int max_points, void *attr_query, void **attr_outdata);
|
||||
int pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 ¢er,
|
||||
float radius, int max_points, bool sort, size_t *out_indices,
|
||||
float *out_distances, int derivs_offset);
|
||||
|
||||
int pointcloud_get(ustring filename, size_t *indices, int count, ustring attr_name,
|
||||
TypeDesc attr_type, void *out_data);
|
||||
|
||||
private:
|
||||
KernelGlobals *kernel_globals;
|
||||
|
||||
#ifdef WITH_PARTIO
|
||||
/* OSL gets pointers to this but its definition is private.
|
||||
* right now it only caches the types already converted to
|
||||
* Partio constants. this is what get_pointcloud_attr_query
|
||||
* returns */
|
||||
struct AttrQuery {
|
||||
/* names of the attributes to query */
|
||||
std::vector<ustring> attr_names;
|
||||
/* types as (enum Partio::ParticleAttributeType) of the
|
||||
* attributes in the query */
|
||||
std::vector<int> attr_partio_types;
|
||||
/* for sanity checks, capacity of the output arrays */
|
||||
int capacity;
|
||||
};
|
||||
|
||||
Partio::ParticlesData *get_pointcloud(ustring filename);
|
||||
|
||||
/* keep a list so adding elements doesn't invalidate pointers */
|
||||
std::list<AttrQuery> m_attr_queries;
|
||||
#endif
|
||||
|
||||
static ustring u_distance;
|
||||
static ustring u_index;
|
||||
static ustring u_camera;
|
||||
|
@@ -36,25 +36,25 @@ tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data);
|
||||
|
||||
void OSLShader::thread_init(KernelGlobals *kg)
|
||||
{
|
||||
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
|
||||
OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData();
|
||||
|
||||
memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
|
||||
tdata->thread_info = ssi->create_thread_info();
|
||||
tdata->thread_info = ss->create_thread_info();
|
||||
|
||||
tls_set(kg->osl.thread_data, tdata);
|
||||
|
||||
((OSLRenderServices *)ssi->renderer())->thread_init(kg);
|
||||
kg->osl.services->thread_init(kg);
|
||||
}
|
||||
|
||||
void OSLShader::thread_free(KernelGlobals *kg)
|
||||
{
|
||||
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
|
||||
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||
|
||||
ssi->destroy_thread_info(tdata->thread_info);
|
||||
ss->destroy_thread_info(tdata->thread_info);
|
||||
|
||||
delete tdata;
|
||||
}
|
||||
@@ -123,7 +123,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
||||
sc.weight = weight;
|
||||
|
||||
switch (prim->category()) {
|
||||
case ClosurePrimitive::BSDF: {
|
||||
case OSL::ClosurePrimitive::BSDF: {
|
||||
if (sd->num_closure == MAX_CLOSURE)
|
||||
return;
|
||||
|
||||
@@ -137,11 +137,9 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
||||
/* sample weight */
|
||||
float albedo = bsdf->albedo(TO_VEC3(sd->I));
|
||||
float sample_weight = fabsf(average(weight)) * albedo;
|
||||
float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight;
|
||||
|
||||
sc.sample_weight = sample_weight;
|
||||
sc.type = CLOSURE_BSDF_ID;
|
||||
sd->osl_closure.bsdf_sample_sum = sample_sum;
|
||||
|
||||
/* scattering flags */
|
||||
if (scattering == OSL::Labels::DIFFUSE)
|
||||
@@ -155,17 +153,15 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
||||
sd->closure[sd->num_closure++] = sc;
|
||||
break;
|
||||
}
|
||||
case ClosurePrimitive::Emissive: {
|
||||
case OSL::ClosurePrimitive::Emissive: {
|
||||
if (sd->num_closure == MAX_CLOSURE)
|
||||
return;
|
||||
|
||||
/* sample weight */
|
||||
float sample_weight = fabsf(average(weight));
|
||||
float sample_sum = sd->osl_closure.emissive_sample_sum + sample_weight;
|
||||
|
||||
sc.sample_weight = sample_weight;
|
||||
sc.type = CLOSURE_EMISSION_ID;
|
||||
sd->osl_closure.emissive_sample_sum = sample_sum;
|
||||
|
||||
/* flag */
|
||||
sd->flag |= SD_EMISSION;
|
||||
@@ -173,7 +169,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
||||
sd->closure[sd->num_closure++] = sc;
|
||||
break;
|
||||
}
|
||||
case ClosurePrimitive::Holdout:
|
||||
case OSL::ClosurePrimitive::Holdout:
|
||||
if (sd->num_closure == MAX_CLOSURE)
|
||||
return;
|
||||
|
||||
@@ -182,11 +178,11 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
||||
sd->flag |= SD_HOLDOUT;
|
||||
sd->closure[sd->num_closure++] = sc;
|
||||
break;
|
||||
case ClosurePrimitive::BSSRDF:
|
||||
case ClosurePrimitive::Debug:
|
||||
case OSL::ClosurePrimitive::BSSRDF:
|
||||
case OSL::ClosurePrimitive::Debug:
|
||||
break; /* not implemented */
|
||||
case ClosurePrimitive::Background:
|
||||
case ClosurePrimitive::Volume:
|
||||
case OSL::ClosurePrimitive::Background:
|
||||
case OSL::ClosurePrimitive::Volume:
|
||||
break; /* not relevant */
|
||||
}
|
||||
}
|
||||
@@ -205,20 +201,19 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
|
||||
void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
|
||||
{
|
||||
/* gather pointers */
|
||||
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
||||
OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
|
||||
|
||||
/* setup shader globals from shader data */
|
||||
sd->osl_ctx = ctx;
|
||||
shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
|
||||
|
||||
/* execute shader for this point */
|
||||
int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (kg->osl.surface_state[shader])
|
||||
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals);
|
||||
ss->execute(*ctx, *(kg->osl.surface_state[shader]), *globals);
|
||||
|
||||
/* flatten closure tree */
|
||||
sd->num_closure = 0;
|
||||
@@ -263,18 +258,17 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
|
||||
float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
|
||||
{
|
||||
/* gather pointers */
|
||||
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
||||
OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
|
||||
|
||||
/* setup shader globals from shader data */
|
||||
sd->osl_ctx = ctx;
|
||||
shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
|
||||
|
||||
/* execute shader for this point */
|
||||
if (kg->osl.background_state)
|
||||
ctx->execute(OSL::pvt::ShadUseSurface, *kg->osl.background_state, *globals);
|
||||
ss->execute(*ctx, *(kg->osl.background_state), *globals);
|
||||
|
||||
/* return background color immediately */
|
||||
if (globals->Ci)
|
||||
@@ -301,29 +295,27 @@ static void flatten_volume_closure_tree(ShaderData *sd,
|
||||
sc.weight = weight;
|
||||
|
||||
switch (prim->category()) {
|
||||
case ClosurePrimitive::Volume: {
|
||||
case OSL::ClosurePrimitive::Volume: {
|
||||
if (sd->num_closure == MAX_CLOSURE)
|
||||
return;
|
||||
|
||||
/* sample weight */
|
||||
float sample_weight = fabsf(average(weight));
|
||||
float sample_sum = sd->osl_closure.volume_sample_sum + sample_weight;
|
||||
|
||||
sc.sample_weight = sample_weight;
|
||||
sc.type = CLOSURE_VOLUME_ID;
|
||||
sd->osl_closure.volume_sample_sum = sample_sum;
|
||||
|
||||
/* add */
|
||||
sd->closure[sd->num_closure++] = sc;
|
||||
break;
|
||||
}
|
||||
case ClosurePrimitive::Holdout:
|
||||
case ClosurePrimitive::Debug:
|
||||
case OSL::ClosurePrimitive::Holdout:
|
||||
case OSL::ClosurePrimitive::Debug:
|
||||
break; /* not implemented */
|
||||
case ClosurePrimitive::Background:
|
||||
case ClosurePrimitive::BSDF:
|
||||
case ClosurePrimitive::Emissive:
|
||||
case ClosurePrimitive::BSSRDF:
|
||||
case OSL::ClosurePrimitive::Background:
|
||||
case OSL::ClosurePrimitive::BSDF:
|
||||
case OSL::ClosurePrimitive::Emissive:
|
||||
case OSL::ClosurePrimitive::BSSRDF:
|
||||
break; /* not relevant */
|
||||
}
|
||||
}
|
||||
@@ -342,25 +334,19 @@ static void flatten_volume_closure_tree(ShaderData *sd,
|
||||
void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
|
||||
{
|
||||
/* gather pointers */
|
||||
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
||||
OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
|
||||
|
||||
/* setup shader globals from shader data */
|
||||
sd->osl_ctx = ctx;
|
||||
shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
|
||||
|
||||
/* execute shader */
|
||||
int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (kg->osl.volume_state[shader])
|
||||
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals);
|
||||
|
||||
/* retrieve resulting closures */
|
||||
sd->osl_closure.volume_sample_sum = 0.0f;
|
||||
sd->osl_closure.num_volume = 0;
|
||||
sd->osl_closure.randb = randb;
|
||||
ss->execute(*ctx, *(kg->osl.volume_state[shader]), *globals);
|
||||
|
||||
if (globals->Ci)
|
||||
flatten_volume_closure_tree(sd, globals->Ci);
|
||||
@@ -371,31 +357,37 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int
|
||||
void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
/* gather pointers */
|
||||
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||
OSL::ShaderGlobals *globals = &tdata->globals;
|
||||
OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info);
|
||||
OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx;
|
||||
|
||||
/* setup shader globals from shader data */
|
||||
sd->osl_ctx = ctx;
|
||||
shaderdata_to_shaderglobals(kg, sd, 0, globals);
|
||||
|
||||
/* execute shader */
|
||||
int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (kg->osl.displacement_state[shader])
|
||||
ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals);
|
||||
ss->execute(*ctx, *(kg->osl.displacement_state[shader]), *globals);
|
||||
|
||||
/* get back position */
|
||||
sd->P = TO_FLOAT3(globals->P);
|
||||
}
|
||||
|
||||
void OSLShader::release(KernelGlobals *kg, const ShaderData *sd)
|
||||
void OSLShader::init(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl *)kg->osl.ss;
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
|
||||
|
||||
sd->osl_ctx = ss->get_context(tdata->thread_info);
|
||||
}
|
||||
|
||||
ssi->release_context((OSL::pvt::ShadingContext *)sd->osl_ctx, tdata->thread_info);
|
||||
void OSLShader::release(KernelGlobals *kg, ShaderData *sd)
|
||||
{
|
||||
OSL::ShadingSystem *ss = kg->osl.ss;
|
||||
|
||||
ss->release_context((OSL::ShadingContext *)sd->osl_ctx);
|
||||
}
|
||||
|
||||
/* BSDF Closure */
|
||||
@@ -458,9 +450,8 @@ float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
|
||||
{
|
||||
OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim;
|
||||
OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
|
||||
eval += TO_FLOAT3(emissive_eval);
|
||||
|
||||
return eval;
|
||||
return TO_FLOAT3(emissive_eval);
|
||||
}
|
||||
|
||||
/* Volume Closure */
|
||||
|
@@ -46,10 +46,10 @@ namespace OSL = ::OSL;
|
||||
|
||||
class OSLRenderServices;
|
||||
class Scene;
|
||||
class ShaderClosure;
|
||||
class ShaderData;
|
||||
class differential3;
|
||||
class KernelGlobals;
|
||||
struct ShaderClosure;
|
||||
struct ShaderData;
|
||||
struct differential3;
|
||||
struct KernelGlobals;
|
||||
|
||||
class OSLShader {
|
||||
public:
|
||||
@@ -79,7 +79,8 @@ public:
|
||||
const float3 omega_in, const float3 omega_out);
|
||||
|
||||
/* release */
|
||||
static void release(KernelGlobals *kg, const ShaderData *sd);
|
||||
static void init(KernelGlobals *kg, ShaderData *sd);
|
||||
static void release(KernelGlobals *kg, ShaderData *sd);
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -154,6 +154,7 @@ CCL_NAMESPACE_END
|
||||
#include "svm_value.h"
|
||||
#include "svm_voronoi.h"
|
||||
#include "svm_checker.h"
|
||||
#include "svm_brick.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
@@ -220,6 +221,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
|
||||
case NODE_TEX_IMAGE:
|
||||
svm_node_tex_image(kg, sd, stack, node);
|
||||
break;
|
||||
case NODE_TEX_IMAGE_BOX:
|
||||
svm_node_tex_image_box(kg, sd, stack, node);
|
||||
break;
|
||||
case NODE_TEX_ENVIRONMENT:
|
||||
svm_node_tex_environment(kg, sd, stack, node);
|
||||
break;
|
||||
@@ -249,6 +253,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
|
||||
case NODE_TEX_CHECKER:
|
||||
svm_node_tex_checker(kg, sd, stack, node, &offset);
|
||||
break;
|
||||
case NODE_TEX_BRICK:
|
||||
svm_node_tex_brick(kg, sd, stack, node, &offset);
|
||||
break;
|
||||
#endif
|
||||
case NODE_CAMERA:
|
||||
svm_node_camera(kg, sd, stack, node.y, node.z, node.w);
|
||||
|
114
intern/cycles/kernel/svm/svm_brick.h
Normal file
114
intern/cycles/kernel/svm/svm_brick.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2012, Blender Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Brick */
|
||||
|
||||
__device_noinline float brick_noise(int n) /* fast integer noise */
|
||||
{
|
||||
int nn;
|
||||
n = (n >> 13) ^ n;
|
||||
nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
|
||||
return 0.5f * ((float)nn / 1073741824.0f);
|
||||
}
|
||||
|
||||
__device_noinline float svm_brick(float3 p, float scale, float mortar_size, float bias,
|
||||
float brick_width, float row_height, float offset_amount, int offset_frequency,
|
||||
float squash_amount, int squash_frequency, float *tint)
|
||||
{
|
||||
p *= scale;
|
||||
|
||||
int bricknum, rownum;
|
||||
float offset = 0.0f;
|
||||
float x, y;
|
||||
|
||||
rownum = (int)floor(p.y / row_height);
|
||||
|
||||
if(offset_frequency && squash_frequency) {
|
||||
brick_width *= ((int)(rownum) % squash_frequency ) ? 1.0f : squash_amount; /* squash */
|
||||
offset = ((int)(rownum) % offset_frequency ) ? 0 : (brick_width*offset_amount); /* offset */
|
||||
}
|
||||
|
||||
bricknum = (int)floor((p.x+offset) / brick_width);
|
||||
|
||||
x = (p.x+offset) - brick_width*bricknum;
|
||||
y = p.y - row_height*rownum;
|
||||
|
||||
*tint = clamp((brick_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0f, 1.0f);
|
||||
|
||||
return (x < mortar_size || y < mortar_size ||
|
||||
x > (brick_width - mortar_size) ||
|
||||
y > (row_height - mortar_size)) ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
__device void svm_node_tex_brick(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
|
||||
{
|
||||
uint4 node2 = read_node(kg, offset);
|
||||
uint4 node3 = read_node(kg, offset);
|
||||
|
||||
/* Input and Output Sockets */
|
||||
uint co_offset, color1_offset, color2_offset, mortar_offset, scale_offset;
|
||||
uint mortar_size_offset, bias_offset, brick_width_offset, row_height_offset;
|
||||
uint color_offset, fac_offset;
|
||||
|
||||
/* RNA properties */
|
||||
uint offset_frequency, squash_frequency;
|
||||
|
||||
float tint = 0.0f;
|
||||
|
||||
decode_node_uchar4(node.y, &co_offset, &color1_offset, &color2_offset, &mortar_offset);
|
||||
decode_node_uchar4(node.z, &scale_offset, &mortar_size_offset, &bias_offset, &brick_width_offset);
|
||||
decode_node_uchar4(node.w, &row_height_offset, &color_offset, &fac_offset, NULL);
|
||||
|
||||
decode_node_uchar4(node2.x, &offset_frequency, &squash_frequency, NULL, NULL);
|
||||
|
||||
float3 co = stack_load_float3(stack, co_offset);
|
||||
|
||||
float3 color1 = stack_load_float3(stack, color1_offset);
|
||||
float3 color2 = stack_load_float3(stack, color2_offset);
|
||||
float3 mortar = stack_load_float3(stack, mortar_offset);
|
||||
|
||||
float scale = stack_load_float_default(stack, scale_offset, node2.y);
|
||||
float mortar_size = stack_load_float_default(stack, mortar_size_offset, node2.z);
|
||||
float bias = stack_load_float_default(stack, bias_offset, node2.w);
|
||||
float brick_width = stack_load_float_default(stack, brick_width_offset, node3.x);
|
||||
float row_height = stack_load_float_default(stack, row_height_offset, node3.y);
|
||||
float offset_amount = __int_as_float(node3.z);
|
||||
float squash_amount = __int_as_float(node3.w);
|
||||
|
||||
float f = svm_brick(co, scale, mortar_size, bias, brick_width, row_height,
|
||||
offset_amount, offset_frequency, squash_amount, squash_frequency,
|
||||
&tint);
|
||||
|
||||
if(f != 1.0f) {
|
||||
float facm = 1.0f - tint;
|
||||
|
||||
color1.x = facm * (color1.x) + tint * color2.x;
|
||||
color1.y = facm * (color1.y) + tint * color2.y;
|
||||
color1.z = facm * (color1.z) + tint * color2.z;
|
||||
}
|
||||
|
||||
if(stack_valid(color_offset))
|
||||
stack_store_float3(stack, color_offset, (f == 1.0f)? mortar: color1);
|
||||
if(stack_valid(fac_offset))
|
||||
stack_store_float(stack, fac_offset, f);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -98,25 +98,47 @@ __device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *sta
|
||||
|
||||
__device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
|
||||
{
|
||||
float data;
|
||||
|
||||
switch(type) {
|
||||
case NODE_INFO_PAR_INDEX: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
data = particle_index(kg, particle_id);
|
||||
stack_store_float(stack, out_offset, data);
|
||||
stack_store_float(stack, out_offset, particle_index(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_AGE: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
data = particle_age(kg, particle_id);
|
||||
stack_store_float(stack, out_offset, data);
|
||||
stack_store_float(stack, out_offset, particle_age(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_LIFETIME: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
data = particle_lifetime(kg, particle_id);
|
||||
stack_store_float(stack, out_offset, data);
|
||||
stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_LOCATION: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
#if 0 /* XXX float4 currently not supported in SVM stack */
|
||||
case NODE_INFO_PAR_ROTATION: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case NODE_INFO_PAR_SIZE: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float(stack, out_offset, particle_size(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_VELOCITY: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
case NODE_INFO_PAR_ANGULAR_VELOCITY: {
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ __device_inline float svm_image_texture_frac(float x, int *ix)
|
||||
return x - (float)i;
|
||||
}
|
||||
|
||||
__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
|
||||
__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb)
|
||||
{
|
||||
uint4 info = kernel_tex_fetch(__tex_image_packed_info, id);
|
||||
uint width = info.x;
|
||||
@@ -82,15 +82,24 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
|
||||
r += ty*(1.0f - tx)*svm_image_texture_read(kg, offset + ix + niy*width);
|
||||
r += ty*tx*svm_image_texture_read(kg, offset + nix + niy*width);
|
||||
|
||||
if(srgb) {
|
||||
r.x = color_srgb_to_scene_linear(r.x);
|
||||
r.y = color_srgb_to_scene_linear(r.y);
|
||||
r.z = color_srgb_to_scene_linear(r.z);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
|
||||
__device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb)
|
||||
{
|
||||
float4 r;
|
||||
|
||||
#ifdef __KERNEL_CPU__
|
||||
r = kernel_tex_image_interp(id, x, y);
|
||||
#else
|
||||
/* not particularly proud of this massive switch, what are the
|
||||
* alternatives?
|
||||
* - use a single big 1D texture, and do our own lookup/filtering
|
||||
@@ -101,11 +110,11 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
|
||||
* we still need some for other storage */
|
||||
|
||||
switch(id) {
|
||||
case 0: r = kernel_tex_image_interp(__tex_image_000, x, y); break;
|
||||
case 1: r = kernel_tex_image_interp(__tex_image_001, x, y); break;
|
||||
case 2: r = kernel_tex_image_interp(__tex_image_002, x, y); break;
|
||||
case 3: r = kernel_tex_image_interp(__tex_image_003, x, y); break;
|
||||
case 4: r = kernel_tex_image_interp(__tex_image_004, x, y); break;
|
||||
case 0: r = kernel_tex_image_interp(__tex_image_float_000, x, y); break;
|
||||
case 1: r = kernel_tex_image_interp(__tex_image_float_001, x, y); break;
|
||||
case 2: r = kernel_tex_image_interp(__tex_image_float_002, x, y); break;
|
||||
case 3: r = kernel_tex_image_interp(__tex_image_float_003, x, y); break;
|
||||
case 4: r = kernel_tex_image_interp(__tex_image_float_004, x, y); break;
|
||||
case 5: r = kernel_tex_image_interp(__tex_image_005, x, y); break;
|
||||
case 6: r = kernel_tex_image_interp(__tex_image_006, x, y); break;
|
||||
case 7: r = kernel_tex_image_interp(__tex_image_007, x, y); break;
|
||||
@@ -196,15 +205,22 @@ __device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y)
|
||||
case 92: r = kernel_tex_image_interp(__tex_image_092, x, y); break;
|
||||
case 93: r = kernel_tex_image_interp(__tex_image_093, x, y); break;
|
||||
case 94: r = kernel_tex_image_interp(__tex_image_094, x, y); break;
|
||||
case 95: r = kernel_tex_image_interp(__tex_image_float_095, x, y); break;
|
||||
case 96: r = kernel_tex_image_interp(__tex_image_float_096, x, y); break;
|
||||
case 97: r = kernel_tex_image_interp(__tex_image_float_097, x, y); break;
|
||||
case 98: r = kernel_tex_image_interp(__tex_image_float_098, x, y); break;
|
||||
case 99: r = kernel_tex_image_interp(__tex_image_float_099, x, y); break;
|
||||
case 95: r = kernel_tex_image_interp(__tex_image_095, x, y); break;
|
||||
case 96: r = kernel_tex_image_interp(__tex_image_096, x, y); break;
|
||||
case 97: r = kernel_tex_image_interp(__tex_image_097, x, y); break;
|
||||
case 98: r = kernel_tex_image_interp(__tex_image_098, x, y); break;
|
||||
case 99: r = kernel_tex_image_interp(__tex_image_099, x, y); break;
|
||||
default:
|
||||
kernel_assert(0);
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(srgb) {
|
||||
r.x = color_srgb_to_scene_linear(r.x);
|
||||
r.y = color_srgb_to_scene_linear(r.y);
|
||||
r.z = color_srgb_to_scene_linear(r.z);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -219,21 +235,102 @@ __device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack
|
||||
decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
|
||||
|
||||
float3 co = stack_load_float3(stack, co_offset);
|
||||
float4 f = svm_image_texture(kg, id, co.x, co.y);
|
||||
float3 r = make_float3(f.x, f.y, f.z);
|
||||
|
||||
if(srgb) {
|
||||
r.x = color_srgb_to_scene_linear(r.x);
|
||||
r.y = color_srgb_to_scene_linear(r.y);
|
||||
r.z = color_srgb_to_scene_linear(r.z);
|
||||
}
|
||||
float4 f = svm_image_texture(kg, id, co.x, co.y, srgb);
|
||||
|
||||
if(stack_valid(out_offset))
|
||||
stack_store_float3(stack, out_offset, r);
|
||||
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
|
||||
if(stack_valid(alpha_offset))
|
||||
stack_store_float(stack, alpha_offset, f.w);
|
||||
}
|
||||
|
||||
__device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
|
||||
{
|
||||
/* get object space normal */
|
||||
float3 N = sd->N;
|
||||
|
||||
N = sd->N;
|
||||
if(sd->object != ~0)
|
||||
object_inverse_normal_transform(kg, sd, &N);
|
||||
|
||||
/* project from direction vector to barycentric coordinates in triangles */
|
||||
N.x = fabsf(N.x);
|
||||
N.y = fabsf(N.y);
|
||||
N.z = fabsf(N.z);
|
||||
|
||||
N /= (N.x + N.y + N.z);
|
||||
|
||||
/* basic idea is to think of this as a triangle, each corner representing
|
||||
* one of the 3 faces of the cube. in the corners we have single textures,
|
||||
* in between we blend between two textures, and in the middle we a blend
|
||||
* between three textures.
|
||||
*
|
||||
* the Nxyz values are the barycentric coordinates in an equilateral
|
||||
* triangle, which in case of blending in the middle has a smaller
|
||||
* equilateral triangle where 3 textures blend. this divides things into
|
||||
* 7 zones, with an if() test for each zone */
|
||||
|
||||
float3 weight = make_float3(0.0f, 0.0f, 0.0f);
|
||||
float blend = __int_as_float(node.w);
|
||||
float limit = 0.5f*(1.0f + blend);
|
||||
|
||||
/* first test for corners with single texture */
|
||||
if(N.x > limit*(N.x + N.y) && N.x > limit*(N.x + N.z)) {
|
||||
weight.x = 1.0f;
|
||||
}
|
||||
else if(N.y > limit*(N.x + N.y) && N.y > limit*(N.y + N.z)) {
|
||||
weight.y = 1.0f;
|
||||
}
|
||||
else if(N.z > limit*(N.x + N.z) && N.z > limit*(N.y + N.z)) {
|
||||
weight.z = 1.0f;
|
||||
}
|
||||
else if(blend > 0.0f) {
|
||||
/* in case of blending, test for mixes between two textures */
|
||||
if(N.z < (1.0f - limit)*(N.y + N.x)) {
|
||||
weight.x = N.x/(N.x + N.y);
|
||||
weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
|
||||
weight.y = 1.0f - weight.x;
|
||||
}
|
||||
else if(N.x < (1.0f - limit)*(N.y + N.z)) {
|
||||
weight.y = N.y/(N.y + N.z);
|
||||
weight.y = clamp((weight.y - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
|
||||
weight.z = 1.0f - weight.y;
|
||||
}
|
||||
else if(N.y < (1.0f - limit)*(N.x + N.z)) {
|
||||
weight.x = N.x/(N.x + N.z);
|
||||
weight.x = clamp((weight.x - 0.5f*(1.0f - blend))/blend, 0.0f, 1.0f);
|
||||
weight.z = 1.0f - weight.x;
|
||||
}
|
||||
else {
|
||||
/* last case, we have a mix between three */
|
||||
weight.x = ((2.0f - limit)*N.x + (limit - 1.0f))/(2.0f*limit - 1.0f);
|
||||
weight.y = ((2.0f - limit)*N.y + (limit - 1.0f))/(2.0f*limit - 1.0f);
|
||||
weight.z = ((2.0f - limit)*N.z + (limit - 1.0f))/(2.0f*limit - 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
/* now fetch textures */
|
||||
uint co_offset, out_offset, alpha_offset, srgb;
|
||||
decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
|
||||
|
||||
float3 co = stack_load_float3(stack, co_offset);
|
||||
uint id = node.y;
|
||||
|
||||
float4 f = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
if(weight.x > 0.0f)
|
||||
f += weight.x*svm_image_texture(kg, id, co.y, co.z, srgb);
|
||||
if(weight.y > 0.0f)
|
||||
f += weight.y*svm_image_texture(kg, id, co.x, co.z, srgb);
|
||||
if(weight.z > 0.0f)
|
||||
f += weight.z*svm_image_texture(kg, id, co.y, co.x, srgb);
|
||||
|
||||
if(stack_valid(out_offset))
|
||||
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
|
||||
if(stack_valid(alpha_offset))
|
||||
stack_store_float(stack, alpha_offset, f.w);
|
||||
}
|
||||
|
||||
|
||||
__device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
|
||||
{
|
||||
uint id = node.y;
|
||||
@@ -252,17 +349,10 @@ __device void svm_node_tex_environment(KernelGlobals *kg, ShaderData *sd, float
|
||||
else
|
||||
uv = direction_to_mirrorball(co);
|
||||
|
||||
float4 f = svm_image_texture(kg, id, uv.x, uv.y);
|
||||
float3 r = make_float3(f.x, f.y, f.z);
|
||||
|
||||
if(srgb) {
|
||||
r.x = color_srgb_to_scene_linear(r.x);
|
||||
r.y = color_srgb_to_scene_linear(r.y);
|
||||
r.z = color_srgb_to_scene_linear(r.z);
|
||||
}
|
||||
float4 f = svm_image_texture(kg, id, uv.x, uv.y, srgb);
|
||||
|
||||
if(stack_valid(out_offset))
|
||||
stack_store_float3(stack, out_offset, r);
|
||||
stack_store_float3(stack, out_offset, make_float3(f.x, f.y, f.z));
|
||||
if(stack_valid(alpha_offset))
|
||||
stack_store_float(stack, alpha_offset, f.w);
|
||||
}
|
||||
|
@@ -108,6 +108,8 @@ __device float svm_math(NodeMath type, float Fac1, float Fac2)
|
||||
Fac = Fac1 < Fac2;
|
||||
else if(type == NODE_MATH_GREATER_THAN)
|
||||
Fac = Fac1 > Fac2;
|
||||
else if(type == NODE_MATH_CLAMP)
|
||||
Fac = clamp(Fac1, 0.0f, 1.0f);
|
||||
else
|
||||
Fac = 0.0f;
|
||||
|
||||
|
@@ -276,6 +276,17 @@ __device float3 svm_mix_linear(float t, float3 col1, float3 col2)
|
||||
return outcol;
|
||||
}
|
||||
|
||||
__device float3 svm_mix_clamp(float3 col)
|
||||
{
|
||||
float3 outcol = col;
|
||||
|
||||
outcol.x = clamp(col.x, 0.0f, 1.0f);
|
||||
outcol.y = clamp(col.y, 0.0f, 1.0f);
|
||||
outcol.z = clamp(col.z, 0.0f, 1.0f);
|
||||
|
||||
return outcol;
|
||||
}
|
||||
|
||||
__device float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2)
|
||||
{
|
||||
float t = clamp(fac, 0.0f, 1.0f);
|
||||
@@ -299,6 +310,7 @@ __device float3 svm_mix(NodeMix type, float fac, float3 c1, float3 c2)
|
||||
case NODE_MIX_COLOR: return svm_mix_color(t, c1, c2);
|
||||
case NODE_MIX_SOFT: return svm_mix_soft(t, c1, c2);
|
||||
case NODE_MIX_LINEAR: return svm_mix_linear(t, c1, c2);
|
||||
case NODE_MIX_CLAMP: return svm_mix_clamp(c1);
|
||||
}
|
||||
|
||||
return make_float3(0.0f, 0.0f, 0.0f);
|
||||
|
@@ -29,7 +29,7 @@ __device_inline float3 svm_background_offset(KernelGlobals *kg)
|
||||
__device_inline float3 svm_world_to_ndc(KernelGlobals *kg, ShaderData *sd, float3 P)
|
||||
{
|
||||
if(kernel_data.cam.type != CAMERA_PANORAMA) {
|
||||
if(sd->object != ~0)
|
||||
if(sd->object == ~0)
|
||||
P += svm_background_offset(kg);
|
||||
|
||||
Transform tfm = kernel_data.cam.worldtondc;
|
||||
|
@@ -40,6 +40,7 @@ typedef enum NodeType {
|
||||
NODE_MIX_CLOSURE,
|
||||
NODE_JUMP,
|
||||
NODE_TEX_IMAGE,
|
||||
NODE_TEX_IMAGE_BOX,
|
||||
NODE_TEX_SKY,
|
||||
NODE_GEOMETRY,
|
||||
NODE_LIGHT_PATH,
|
||||
@@ -89,7 +90,8 @@ typedef enum NodeType {
|
||||
NODE_MIN_MAX,
|
||||
NODE_LIGHT_FALLOFF,
|
||||
NODE_OBJECT_INFO,
|
||||
NODE_PARTICLE_INFO
|
||||
NODE_PARTICLE_INFO,
|
||||
NODE_TEX_BRICK
|
||||
} NodeType;
|
||||
|
||||
typedef enum NodeAttributeType {
|
||||
@@ -116,7 +118,12 @@ typedef enum NodeObjectInfo {
|
||||
typedef enum NodeParticleInfo {
|
||||
NODE_INFO_PAR_INDEX,
|
||||
NODE_INFO_PAR_AGE,
|
||||
NODE_INFO_PAR_LIFETIME
|
||||
NODE_INFO_PAR_LIFETIME,
|
||||
NODE_INFO_PAR_LOCATION,
|
||||
NODE_INFO_PAR_ROTATION,
|
||||
NODE_INFO_PAR_SIZE,
|
||||
NODE_INFO_PAR_VELOCITY,
|
||||
NODE_INFO_PAR_ANGULAR_VELOCITY
|
||||
} NodeParticleInfo;
|
||||
|
||||
typedef enum NodeLightPath {
|
||||
@@ -163,7 +170,8 @@ typedef enum NodeMix {
|
||||
NODE_MIX_VAL,
|
||||
NODE_MIX_COLOR,
|
||||
NODE_MIX_SOFT,
|
||||
NODE_MIX_LINEAR
|
||||
NODE_MIX_LINEAR,
|
||||
NODE_MIX_CLAMP /* used for the clamp UI option */
|
||||
} NodeMix;
|
||||
|
||||
typedef enum NodeMath {
|
||||
@@ -183,7 +191,8 @@ typedef enum NodeMath {
|
||||
NODE_MATH_MAXIMUM,
|
||||
NODE_MATH_ROUND,
|
||||
NODE_MATH_LESS_THAN,
|
||||
NODE_MATH_GREATER_THAN
|
||||
NODE_MATH_GREATER_THAN,
|
||||
NODE_MATH_CLAMP /* used for the clamp UI option */
|
||||
} NodeMath;
|
||||
|
||||
typedef enum NodeVectorMath {
|
||||
|
@@ -27,6 +27,7 @@ set(SRC
|
||||
nodes.cpp
|
||||
object.cpp
|
||||
osl.cpp
|
||||
particles.cpp
|
||||
scene.cpp
|
||||
session.cpp
|
||||
shader.cpp
|
||||
@@ -51,6 +52,7 @@ set(SRC_HEADERS
|
||||
nodes.h
|
||||
object.h
|
||||
osl.h
|
||||
particles.h
|
||||
scene.h
|
||||
session.h
|
||||
shader.h
|
||||
|
@@ -84,28 +84,6 @@ bool Attribute::same_storage(TypeDesc a, TypeDesc b)
|
||||
return false;
|
||||
}
|
||||
|
||||
ustring Attribute::standard_name(AttributeStandard std)
|
||||
{
|
||||
if(std == ATTR_STD_VERTEX_NORMAL)
|
||||
return ustring("N");
|
||||
else if(std == ATTR_STD_FACE_NORMAL)
|
||||
return ustring("Ng");
|
||||
else if(std == ATTR_STD_UV)
|
||||
return ustring("uv");
|
||||
else if(std == ATTR_STD_GENERATED)
|
||||
return ustring("generated");
|
||||
else if(std == ATTR_STD_POSITION_UNDEFORMED)
|
||||
return ustring("undeformed");
|
||||
else if(std == ATTR_STD_POSITION_UNDISPLACED)
|
||||
return ustring("undisplaced");
|
||||
else if(std == ATTR_STD_MOTION_PRE)
|
||||
return ustring("motion_pre");
|
||||
else if(std == ATTR_STD_MOTION_POST)
|
||||
return ustring("motion_post");
|
||||
|
||||
return ustring();
|
||||
}
|
||||
|
||||
/* Attribute Set */
|
||||
|
||||
AttributeSet::AttributeSet()
|
||||
@@ -176,7 +154,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
|
||||
Attribute *attr = NULL;
|
||||
|
||||
if(name == ustring())
|
||||
name = Attribute::standard_name(std);
|
||||
name = attribute_standard_name(std);
|
||||
|
||||
if(std == ATTR_STD_VERTEX_NORMAL)
|
||||
attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "kernel_types.h"
|
||||
|
||||
#include "util_attribute.h"
|
||||
#include "util_list.h"
|
||||
#include "util_param.h"
|
||||
#include "util_types.h"
|
||||
@@ -71,7 +72,6 @@ public:
|
||||
const float *data_float() const { return (float*)data(); }
|
||||
|
||||
static bool same_storage(TypeDesc a, TypeDesc b);
|
||||
static ustring standard_name(AttributeStandard std);
|
||||
};
|
||||
|
||||
/* Attribute Set
|
||||
|
@@ -74,6 +74,29 @@ int BufferParams::get_passes_size()
|
||||
return align_up(size, 4);
|
||||
}
|
||||
|
||||
/* Render Buffer Task */
|
||||
|
||||
RenderTile::RenderTile()
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = 0;
|
||||
h = 0;
|
||||
|
||||
start_sample = 0;
|
||||
num_samples = 0;
|
||||
resolution = 0;
|
||||
|
||||
offset = 0;
|
||||
stride = 0;
|
||||
|
||||
buffer = 0;
|
||||
rng_state = 0;
|
||||
rgba = 0;
|
||||
|
||||
buffers = NULL;
|
||||
}
|
||||
|
||||
/* Render Buffers */
|
||||
|
||||
RenderBuffers::RenderBuffers(Device *device_)
|
||||
@@ -135,7 +158,7 @@ bool RenderBuffers::copy_from_device()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels)
|
||||
bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
|
||||
{
|
||||
int pass_offset = 0;
|
||||
|
||||
|
@@ -67,12 +67,11 @@ class RenderBuffers {
|
||||
public:
|
||||
/* buffer parameters */
|
||||
BufferParams params;
|
||||
|
||||
/* float buffer */
|
||||
device_vector<float> buffer;
|
||||
/* random number generator state */
|
||||
device_vector<uint> rng_state;
|
||||
/* mutex, must be locked manually by callers */
|
||||
thread_mutex mutex;
|
||||
|
||||
RenderBuffers(Device *device);
|
||||
~RenderBuffers();
|
||||
@@ -80,7 +79,7 @@ public:
|
||||
void reset(Device *device, BufferParams& params);
|
||||
|
||||
bool copy_from_device();
|
||||
bool get_pass(PassType type, float exposure, int sample, int components, float *pixels);
|
||||
bool get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels);
|
||||
|
||||
protected:
|
||||
void device_free();
|
||||
@@ -105,8 +104,6 @@ public:
|
||||
bool transparent;
|
||||
/* byte buffer for tonemapped result */
|
||||
device_vector<uchar4> rgba;
|
||||
/* mutex, must be locked manually by callers */
|
||||
thread_mutex mutex;
|
||||
|
||||
DisplayBuffer(Device *device);
|
||||
~DisplayBuffer();
|
||||
@@ -124,6 +121,28 @@ protected:
|
||||
Device *device;
|
||||
};
|
||||
|
||||
/* Render Tile
|
||||
* Rendering task on a buffer */
|
||||
|
||||
class RenderTile {
|
||||
public:
|
||||
int x, y, w, h;
|
||||
int start_sample;
|
||||
int num_samples;
|
||||
int sample;
|
||||
int resolution;
|
||||
int offset;
|
||||
int stride;
|
||||
|
||||
device_ptr buffer;
|
||||
device_ptr rng_state;
|
||||
device_ptr rgba;
|
||||
|
||||
RenderBuffers *buffers;
|
||||
|
||||
RenderTile();
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BUFFERS_H__ */
|
||||
|
@@ -75,6 +75,7 @@ Camera::Camera()
|
||||
|
||||
need_update = true;
|
||||
need_device_update = true;
|
||||
previous_need_motion = -1;
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
@@ -140,8 +141,17 @@ void Camera::update()
|
||||
|
||||
void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
{
|
||||
Scene::MotionType need_motion = scene->need_motion();
|
||||
|
||||
update();
|
||||
|
||||
if (previous_need_motion != need_motion) {
|
||||
/* scene's motion model could have been changed since previous device
|
||||
* camera update this could happen for example in case when one render
|
||||
* layer has got motion pass and another not */
|
||||
need_device_update = true;
|
||||
}
|
||||
|
||||
if(!need_device_update)
|
||||
return;
|
||||
|
||||
@@ -159,7 +169,6 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
kcam->worldtocamera = transform_inverse(cameratoworld);
|
||||
|
||||
/* camera motion */
|
||||
Scene::MotionType need_motion = scene->need_motion();
|
||||
kcam->have_motion = 0;
|
||||
|
||||
if(need_motion == Scene::MOTION_PASS) {
|
||||
@@ -226,6 +235,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
|
||||
kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
|
||||
|
||||
need_device_update = false;
|
||||
previous_need_motion = need_motion;
|
||||
}
|
||||
|
||||
void Camera::device_free(Device *device, DeviceScene *dscene)
|
||||
|
@@ -91,6 +91,7 @@ public:
|
||||
/* update */
|
||||
bool need_update;
|
||||
bool need_device_update;
|
||||
int previous_need_motion;
|
||||
|
||||
/* functions */
|
||||
Camera();
|
||||
|
@@ -55,6 +55,7 @@ ShaderNode::ShaderNode(const char *name_)
|
||||
name = name_;
|
||||
id = -1;
|
||||
bump = SHADER_BUMP_NONE;
|
||||
special_type = SHADER_SPECIAL_TYPE_NONE;
|
||||
}
|
||||
|
||||
ShaderNode::~ShaderNode()
|
||||
@@ -298,8 +299,8 @@ void ShaderGraph::copy_nodes(set<ShaderNode*>& nodes, map<ShaderNode*, ShaderNod
|
||||
void ShaderGraph::remove_proxy_nodes(vector<bool>& removed)
|
||||
{
|
||||
foreach(ShaderNode *node, nodes) {
|
||||
ProxyNode *proxy = dynamic_cast<ProxyNode*>(node);
|
||||
if (proxy) {
|
||||
if (node->special_type == SHADER_SPECIAL_TYPE_PROXY) {
|
||||
ProxyNode *proxy = static_cast<ProxyNode*>(node);
|
||||
ShaderInput *input = proxy->inputs[0];
|
||||
ShaderOutput *output = proxy->outputs[0];
|
||||
|
||||
@@ -330,9 +331,8 @@ void ShaderGraph::remove_proxy_nodes(vector<bool>& removed)
|
||||
}
|
||||
|
||||
/* remove useless mix closures nodes */
|
||||
MixClosureNode *mix = dynamic_cast<MixClosureNode*>(node);
|
||||
|
||||
if(mix) {
|
||||
if(node->special_type == SHADER_SPECIAL_TYPE_MIX_CLOSURE) {
|
||||
MixClosureNode *mix = static_cast<MixClosureNode*>(node);
|
||||
if(mix->outputs[0]->links.size() && mix->inputs[1]->link == mix->inputs[2]->link) {
|
||||
ShaderOutput *output = mix->inputs[1]->link;
|
||||
vector<ShaderInput*> inputs = mix->outputs[0]->links;
|
||||
@@ -402,6 +402,20 @@ void ShaderGraph::clean()
|
||||
/* break cycles */
|
||||
break_cycles(output(), visited, on_stack);
|
||||
|
||||
/* disconnect unused nodes */
|
||||
foreach(ShaderNode *node, nodes) {
|
||||
if(!visited[node->id]) {
|
||||
foreach(ShaderInput *to, node->inputs) {
|
||||
ShaderOutput *from = to->link;
|
||||
|
||||
if (from) {
|
||||
to->link = NULL;
|
||||
from->links.erase(remove(from->links.begin(), from->links.end(), to), from->links.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* remove unused nodes */
|
||||
foreach(ShaderNode *node, nodes) {
|
||||
if(visited[node->id])
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user