Merged changes in the trunk up to revision 50607.

Conflicts resolved:
source/blender/blenloader/intern/readfile.c
This commit is contained in:
Tamito Kajiyama
2012-09-15 00:15:24 +00:00
615 changed files with 11782 additions and 7376 deletions

View File

@@ -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")

View File

@@ -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

View 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()

View File

@@ -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()

View File

@@ -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'

View File

@@ -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'

View File

@@ -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:

View File

@@ -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)

View File

@@ -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'

View File

@@ -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

View File

@@ -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__

View File

@@ -22,7 +22,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
/** \file audaspace/intern/AUD_Reference.cpp
/** \file audaspace/intern/AUD_ReferenceHandler.cpp
* \ingroup audaspaceintern
*/

View File

@@ -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

View File

@@ -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());

View File

@@ -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")) {

View File

@@ -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="",

View File

@@ -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):

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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);

View File

@@ -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)

View File

@@ -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();
}
};

View File

@@ -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)

View File

@@ -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;

View 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

View 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__ */

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)) {

View 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__ */

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View 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

View File

@@ -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)

View 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;
}

View File

@@ -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;

View File

@@ -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;
}
}

View 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);
}

View File

@@ -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);
}

View File

@@ -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));
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View 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);
}

View 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);
}

View File

@@ -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)
}

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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);
}

View 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 */

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 &center,
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 &center, 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 *)&center, 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

View File

@@ -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 &center, float radius,
int max_points, void *attr_query, void **attr_outdata);
int pointcloud_search(OSL::ShaderGlobals *sg, ustring filename, const OSL::Vec3 &center,
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;

View File

@@ -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 */

View File

@@ -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

View File

@@ -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);

View 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

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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__ */

View File

@@ -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)

View File

@@ -91,6 +91,7 @@ public:
/* update */
bool need_update;
bool need_device_update;
int previous_need_motion;
/* functions */
Camera();

View File

@@ -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