Merged changes in the trunk up to revision 51853.
Conflicts resolved: source/blender/blenloader/intern/readfile.c source/blender/bmesh/operators/bmo_utils.c This commit also includes a fix of a bug identified during the merge and committed in revision 51853. Thanks Thomas (dingto) for the timely fix!
This commit is contained in:
@@ -186,11 +186,11 @@ unset(PLATFORM_DEFAULT)
|
||||
|
||||
|
||||
# Modifiers
|
||||
option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON)
|
||||
option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON)
|
||||
option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
|
||||
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
|
||||
option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF)
|
||||
option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON)
|
||||
option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON)
|
||||
option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
|
||||
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
|
||||
option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF)
|
||||
mark_as_advanced(WITH_MOD_CLOTH_ELTOPO)
|
||||
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF)
|
||||
|
||||
@@ -658,11 +658,7 @@ if(UNIX AND NOT APPLE)
|
||||
else()
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
endif()
|
||||
if(WITH_CYCLES_OSL)
|
||||
find_package(Boost 1.34 COMPONENTS filesystem python3 regex system thread) # osl_nodes uses boost_python
|
||||
else()
|
||||
find_package(Boost 1.34 COMPONENTS filesystem regex system thread)
|
||||
endif()
|
||||
find_package(Boost 1.34 COMPONENTS filesystem regex system thread)
|
||||
mark_as_advanced(Boost_DIR) # why doesnt boost do this?
|
||||
endif()
|
||||
|
||||
@@ -828,7 +824,7 @@ if(UNIX AND NOT APPLE)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(PLATFORM_CFLAGS "-pipe -fPIC -funsigned-char -fno-strict-aliasing")
|
||||
# Solaris CC
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "SunPro")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "SunPro")
|
||||
set(PLATFORM_CFLAGS "-pipe -features=extensions -fPIC -D__FUNCTION__=__func__")
|
||||
|
||||
# Intel C++ Compiler
|
||||
@@ -1137,12 +1133,6 @@ elseif(WIN32)
|
||||
debug libboost_date_time-${BOOST_DEBUG_POSTFIX} debug libboost_filesystem-${BOOST_DEBUG_POSTFIX}
|
||||
debug libboost_regex-${BOOST_DEBUG_POSTFIX}
|
||||
debug libboost_system-${BOOST_DEBUG_POSTFIX} debug libboost_thread-${BOOST_DEBUG_POSTFIX})
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
|
||||
optimized libboost_python3-${BOOST_POSTFIX}
|
||||
debug libboost_python3-${BOOST_DEBUG_POSTFIX})
|
||||
endif(WITH_CYCLES_OSL)
|
||||
|
||||
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB")
|
||||
endif()
|
||||
|
||||
@@ -1323,12 +1313,6 @@ elseif(WIN32)
|
||||
debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX}
|
||||
boost_regex-${BOOST_DEBUG_POSTFIX}
|
||||
boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX})
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(BOOST_LIBRARIES ${BOOST_LIBRARIES}
|
||||
optimized libboost_python3-${BOOST_POSTFIX}
|
||||
debug libboost_python3-${BOOST_DEBUG_POSTFIX})
|
||||
endif(WITH_CYCLES_OSL)
|
||||
|
||||
set(BOOST_LIBPATH ${BOOST}/lib)
|
||||
set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ")
|
||||
endif()
|
||||
@@ -1583,11 +1567,7 @@ elseif(APPLE)
|
||||
if(WITH_BOOST)
|
||||
set(BOOST ${LIBDIR}/boost)
|
||||
set(BOOST_INCLUDE_DIR ${BOOST}/include)
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_python3-mt boost_regex-mt boost_system-mt boost_thread-mt)
|
||||
else(WITH_CYCLES_OSL)
|
||||
set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt)
|
||||
endif(WITH_CYCLES_OSL)
|
||||
set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt)
|
||||
set(BOOST_LIBPATH ${BOOST}/lib)
|
||||
set(BOOST_DEFINITIONS)
|
||||
endif()
|
||||
|
@@ -37,7 +37,7 @@ BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/
|
||||
'${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
|
||||
'/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
|
||||
'/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
|
||||
'/usr/lib/liborc-0.4.a /usr/lib/libasound.a'
|
||||
'/usr/lib/liborc-0.4.a'
|
||||
|
||||
# Don't depend on system's libstdc++
|
||||
WITH_BF_STATICCXX = True
|
||||
|
@@ -37,7 +37,7 @@ BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/
|
||||
'${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
|
||||
'/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
|
||||
'/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
|
||||
'/usr/lib/liborc-0.4.a /usr/lib/libasound.a'
|
||||
'/usr/lib/liborc-0.4.a'
|
||||
|
||||
# Don't depend on system's libstdc++
|
||||
WITH_BF_STATICCXX = True
|
||||
|
@@ -23,7 +23,7 @@ BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/
|
||||
'${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
|
||||
'/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
|
||||
'/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
|
||||
'/usr/lib/liborc-0.4.a /usr/lib/libasound.a'
|
||||
'/usr/lib/liborc-0.4.a'
|
||||
|
||||
# Don't depend on system's libstdc++
|
||||
WITH_BF_STATICCXX = True
|
||||
|
@@ -23,7 +23,7 @@ BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/
|
||||
'${BF_FFMPEG_LIBPATH}/libswscale.a ${BF_FFMPEG_LIBPATH}/libswresample.a ' + \
|
||||
'/usr/lib/libxvidcore.a /usr/lib/libx264.a /usr/lib/libmp3lame.a /usr/lib/libvpx.a /usr/lib/libvorbis.a ' + \
|
||||
'/usr/lib/libogg.a /usr/lib/libvorbisenc.a /usr/lib/libtheora.a /usr/lib/libschroedinger-1.0.a ' + \
|
||||
'/usr/lib/liborc-0.4.a /usr/lib/libasound.a'
|
||||
'/usr/lib/liborc-0.4.a'
|
||||
|
||||
# Don't depend on system's libstdc++
|
||||
WITH_BF_STATICCXX = True
|
||||
|
@@ -81,6 +81,12 @@ else:
|
||||
elif builder.endswith('linux_glibc27_i386_scons'):
|
||||
configs = ['user-config-player-glibc27-i686.py',
|
||||
'user-config-glibc27-i686.py']
|
||||
if builder.endswith('linux_glibc211_x86_64_scons'):
|
||||
configs = ['user-config-player-glibc211-x86_64.py',
|
||||
'user-config-glibc211-x86_64.py']
|
||||
elif builder.endswith('linux_glibc211_i386_scons'):
|
||||
configs = ['user-config-player-glibc211-i686.py',
|
||||
'user-config-glibc211-i686.py']
|
||||
|
||||
for config in configs:
|
||||
config_fpath = os.path.join(config_dir, config)
|
||||
|
@@ -63,6 +63,12 @@ if builder.find('scons') != -1:
|
||||
elif builder.endswith('linux_glibc27_i386_scons'):
|
||||
config = 'user-config-glibc27-i686.py'
|
||||
bits = 32
|
||||
if builder.endswith('linux_glibc211_x86_64_scons'):
|
||||
config = 'user-config-glibc211-x86_64.py'
|
||||
bits = 64
|
||||
elif builder.endswith('linux_glibc211_i386_scons'):
|
||||
config = 'user-config-glibc211-i686.py'
|
||||
bits = 32
|
||||
|
||||
if config is not None:
|
||||
config_fpath = os.path.join(config_dir, config)
|
||||
|
@@ -662,11 +662,16 @@ def buildslave(target=None, source=None, env=None):
|
||||
if platform == 'linux':
|
||||
import platform
|
||||
|
||||
if env['BF_INSTALLDIR'].find('glibc27') != -1:
|
||||
glibc="glibc27"
|
||||
elif env['BF_INSTALLDIR'].find('glibc211') != -1:
|
||||
glibc="glibc211"
|
||||
|
||||
bitness = platform.architecture()[0]
|
||||
if bitness == '64bit':
|
||||
platform = 'linux-glibc27-x86_64'
|
||||
platform = 'linux-' + glibc + '-x86_64'
|
||||
elif bitness == '32bit':
|
||||
platform = 'linux-glibc27-i686'
|
||||
platform = 'linux-' + glibc + '-i686'
|
||||
if platform == 'darwin':
|
||||
platform = 'OSX-' + env['MACOSX_ARCHITECTURE']
|
||||
|
||||
|
@@ -918,6 +918,72 @@ def pymodule2sphinx(basepath, module_name, module, title):
|
||||
|
||||
file.close()
|
||||
|
||||
# Changes in blender will force errors here
|
||||
context_type_map = {
|
||||
"active_base": ("ObjectBase", False),
|
||||
"active_bone": ("EditBone", False),
|
||||
"active_object": ("Object", False),
|
||||
"active_operator": ("Operator", False),
|
||||
"active_pose_bone": ("PoseBone", False),
|
||||
"active_node": ("Node", False),
|
||||
"armature": ("Armature", False),
|
||||
"bone": ("Bone", False),
|
||||
"brush": ("Brush", False),
|
||||
"camera": ("Camera", False),
|
||||
"cloth": ("ClothModifier", False),
|
||||
"collision": ("CollisionModifier", False),
|
||||
"curve": ("Curve", False),
|
||||
"dynamic_paint": ("DynamicPaintModifier", False),
|
||||
"edit_bone": ("EditBone", False),
|
||||
"edit_image": ("Image", False),
|
||||
"edit_mask": ("Mask", False),
|
||||
"edit_movieclip": ("MovieClip", False),
|
||||
"edit_object": ("Object", False),
|
||||
"edit_text": ("Text", False),
|
||||
"editable_bones": ("EditBone", True),
|
||||
"fluid": ("FluidSimulationModifier", False),
|
||||
"image_paint_object": ("Object", False),
|
||||
"lamp": ("Lamp", False),
|
||||
"lattice": ("Lattice", False),
|
||||
"material": ("Material", False),
|
||||
"material_slot": ("MaterialSlot", False),
|
||||
"mesh": ("Mesh", False),
|
||||
"meta_ball": ("MetaBall", False),
|
||||
"object": ("Object", False),
|
||||
"particle_edit_object": ("Object", False),
|
||||
"particle_settings": ("ParticleSettings", False),
|
||||
"particle_system": ("ParticleSystem", False),
|
||||
"particle_system_editable": ("ParticleSystem", False),
|
||||
"pose_bone": ("PoseBone", False),
|
||||
"scene": ("Scene", False),
|
||||
"sculpt_object": ("Object", False),
|
||||
"selectable_bases": ("ObjectBase", True),
|
||||
"selectable_objects": ("Object", True),
|
||||
"selected_bases": ("ObjectBase", True),
|
||||
"selected_bones": ("EditBone", True),
|
||||
"selected_editable_bases": ("ObjectBase", True),
|
||||
"selected_editable_bones": ("EditBone", True),
|
||||
"selected_editable_objects": ("Object", True),
|
||||
"selected_editable_sequences": ("Sequence", True),
|
||||
"selected_nodes": ("Node", True),
|
||||
"selected_objects": ("Object", True),
|
||||
"selected_pose_bones": ("PoseBone", True),
|
||||
"selected_sequences": ("Sequence", True),
|
||||
"sequences": ("Sequence", True),
|
||||
"smoke": ("SmokeModifier", False),
|
||||
"soft_body": ("SoftBodyModifier", False),
|
||||
"speaker": ("Speaker", False),
|
||||
"texture": ("Texture", False),
|
||||
"texture_slot": ("MaterialTextureSlot", False),
|
||||
"texture_user": ("ID", False),
|
||||
"vertex_paint_object": ("Object", False),
|
||||
"visible_bases": ("ObjectBase", True),
|
||||
"visible_bones": ("EditBone", True),
|
||||
"visible_objects": ("Object", True),
|
||||
"visible_pose_bones": ("PoseBone", True),
|
||||
"weight_paint_object": ("Object", False),
|
||||
"world": ("World", False),
|
||||
}
|
||||
|
||||
def pycontext2sphinx(basepath):
|
||||
# Only use once. very irregular
|
||||
@@ -946,72 +1012,6 @@ def pycontext2sphinx(basepath):
|
||||
"sequencer_context_dir",
|
||||
)
|
||||
|
||||
# Changes in blender will force errors here
|
||||
type_map = {
|
||||
"active_base": ("ObjectBase", False),
|
||||
"active_bone": ("Bone", False),
|
||||
"active_object": ("Object", False),
|
||||
"active_operator": ("Operator", False),
|
||||
"active_pose_bone": ("PoseBone", False),
|
||||
"active_node": ("Node", False),
|
||||
"armature": ("Armature", False),
|
||||
"bone": ("Bone", False),
|
||||
"brush": ("Brush", False),
|
||||
"camera": ("Camera", False),
|
||||
"cloth": ("ClothModifier", False),
|
||||
"collision": ("CollisionModifier", False),
|
||||
"curve": ("Curve", False),
|
||||
"dynamic_paint": ("DynamicPaintModifier", False),
|
||||
"edit_bone": ("EditBone", False),
|
||||
"edit_image": ("Image", False),
|
||||
"edit_mask": ("Mask", False),
|
||||
"edit_movieclip": ("MovieClip", False),
|
||||
"edit_object": ("Object", False),
|
||||
"edit_text": ("Text", False),
|
||||
"editable_bones": ("EditBone", True),
|
||||
"fluid": ("FluidSimulationModifier", False),
|
||||
"image_paint_object": ("Object", False),
|
||||
"lamp": ("Lamp", False),
|
||||
"lattice": ("Lattice", False),
|
||||
"material": ("Material", False),
|
||||
"material_slot": ("MaterialSlot", False),
|
||||
"mesh": ("Mesh", False),
|
||||
"meta_ball": ("MetaBall", False),
|
||||
"object": ("Object", False),
|
||||
"particle_edit_object": ("Object", False),
|
||||
"particle_settings": ("ParticleSettings", False),
|
||||
"particle_system": ("ParticleSystem", False),
|
||||
"particle_system_editable": ("ParticleSystem", False),
|
||||
"pose_bone": ("PoseBone", False),
|
||||
"scene": ("Scene", False),
|
||||
"sculpt_object": ("Object", False),
|
||||
"selectable_bases": ("ObjectBase", True),
|
||||
"selectable_objects": ("Object", True),
|
||||
"selected_bases": ("ObjectBase", True),
|
||||
"selected_bones": ("Bone", True),
|
||||
"selected_editable_bases": ("ObjectBase", True),
|
||||
"selected_editable_bones": ("Bone", True),
|
||||
"selected_editable_objects": ("Object", True),
|
||||
"selected_editable_sequences": ("Sequence", True),
|
||||
"selected_nodes": ("Node", True),
|
||||
"selected_objects": ("Object", True),
|
||||
"selected_pose_bones": ("PoseBone", True),
|
||||
"selected_sequences": ("Sequence", True),
|
||||
"sequences": ("Sequence", True),
|
||||
"smoke": ("SmokeModifier", False),
|
||||
"soft_body": ("SoftBodyModifier", False),
|
||||
"speaker": ("Speaker", False),
|
||||
"texture": ("Texture", False),
|
||||
"texture_slot": ("MaterialTextureSlot", False),
|
||||
"texture_user": ("ID", False),
|
||||
"vertex_paint_object": ("Object", False),
|
||||
"visible_bases": ("ObjectBase", True),
|
||||
"visible_bones": ("Object", True),
|
||||
"visible_objects": ("Object", True),
|
||||
"visible_pose_bones": ("PoseBone", True),
|
||||
"weight_paint_object": ("Object", False),
|
||||
"world": ("World", False),
|
||||
}
|
||||
|
||||
unique = set()
|
||||
blend_cdll = ctypes.CDLL("")
|
||||
@@ -1026,7 +1026,7 @@ def pycontext2sphinx(basepath):
|
||||
while char_array[i] is not None:
|
||||
member = ctypes.string_at(char_array[i]).decode(encoding="ascii")
|
||||
fw(".. data:: %s\n\n" % member)
|
||||
member_type, is_seq = type_map[member]
|
||||
member_type, is_seq = context_type_map[member]
|
||||
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))
|
||||
unique.add(member)
|
||||
i += 1
|
||||
@@ -1034,8 +1034,8 @@ def pycontext2sphinx(basepath):
|
||||
# generate typemap...
|
||||
# for member in sorted(unique):
|
||||
# print(' "%s": ("", False),' % member)
|
||||
if len(type_map) > len(unique):
|
||||
raise Exception("Some types are not used: %s" % str([member for member in type_map if member not in unique]))
|
||||
if len(context_type_map) > len(unique):
|
||||
raise Exception("Some types are not used: %s" % str([member for member in context_type_map if member not in unique]))
|
||||
else:
|
||||
pass # will have raised an error above
|
||||
|
||||
@@ -1322,6 +1322,13 @@ def pyrna2sphinx(basepath):
|
||||
fw(".. hlist::\n")
|
||||
fw(" :columns: 2\n\n")
|
||||
|
||||
# context does its own thing
|
||||
# "active_base": ("ObjectBase", False),
|
||||
for ref_attr, (ref_type, ref_is_seq) in sorted(context_type_map.items()):
|
||||
if ref_type == struct_id:
|
||||
fw(" * :mod:`bpy.context.%s`\n" % ref_attr)
|
||||
del ref_attr, ref_type, ref_is_seq
|
||||
|
||||
for ref in struct.references:
|
||||
ref_split = ref.split(".")
|
||||
if len(ref_split) > 2:
|
||||
|
@@ -174,21 +174,34 @@ bool AUD_OpenALDevice::AUD_OpenALHandle::stop()
|
||||
if(!m_status)
|
||||
return false;
|
||||
|
||||
// AUD_XXX Create a reference of our own object so that it doesn't get
|
||||
// deleted before the end of this function
|
||||
AUD_Reference<AUD_OpenALHandle> This = this;
|
||||
|
||||
if(m_status == AUD_STATUS_PLAYING)
|
||||
m_device->m_playingSounds.remove(This);
|
||||
else
|
||||
m_device->m_pausedSounds.remove(This);
|
||||
m_status = AUD_STATUS_INVALID;
|
||||
|
||||
alDeleteSources(1, &m_source);
|
||||
if(!m_isBuffered)
|
||||
alDeleteBuffers(CYCLE_BUFFERS, m_buffers);
|
||||
|
||||
m_status = AUD_STATUS_INVALID;
|
||||
return true;
|
||||
for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
|
||||
{
|
||||
if(it->get() == this)
|
||||
{
|
||||
AUD_Reference<AUD_OpenALHandle> This = *it;
|
||||
|
||||
m_device->m_playingSounds.erase(it);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
|
||||
{
|
||||
if(it->get() == this)
|
||||
{
|
||||
m_device->m_pausedSounds.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AUD_OpenALDevice::AUD_OpenALHandle::getKeep()
|
||||
|
@@ -277,22 +277,33 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::stop()
|
||||
if(!m_status)
|
||||
return false;
|
||||
|
||||
// AUD_XXX Create a reference of our own object so that it doesn't get
|
||||
// deleted before the end of this function
|
||||
AUD_Reference<AUD_SoftwareHandle> This = this;
|
||||
|
||||
if(m_status == AUD_STATUS_PLAYING)
|
||||
{
|
||||
m_device->m_playingSounds.remove(This);
|
||||
|
||||
if(m_device->m_playingSounds.empty())
|
||||
m_device->playing(m_device->m_playback = false);
|
||||
}
|
||||
else
|
||||
m_device->m_pausedSounds.remove(This);
|
||||
|
||||
m_status = AUD_STATUS_INVALID;
|
||||
return true;
|
||||
|
||||
for(AUD_HandleIterator it = m_device->m_playingSounds.begin(); it != m_device->m_playingSounds.end(); it++)
|
||||
{
|
||||
if(it->get() == this)
|
||||
{
|
||||
AUD_Reference<AUD_SoftwareHandle> This = *it;
|
||||
|
||||
m_device->m_playingSounds.erase(it);
|
||||
|
||||
if(m_device->m_playingSounds.empty())
|
||||
m_device->playing(m_device->m_playback = false);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for(AUD_HandleIterator it = m_device->m_pausedSounds.begin(); it != m_device->m_pausedSounds.end(); it++)
|
||||
{
|
||||
if(it->get() == this)
|
||||
{
|
||||
m_device->m_pausedSounds.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AUD_SoftwareDevice::AUD_SoftwareHandle::getKeep()
|
||||
|
8
intern/bsp/extern/CSG_BooleanOps.h
vendored
8
intern/bsp/extern/CSG_BooleanOps.h
vendored
@@ -61,9 +61,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int vertex_index[4];
|
||||
int vertex_number;
|
||||
int orig_face;
|
||||
int vertex_index[4];
|
||||
int vertex_number;
|
||||
int orig_face;
|
||||
} CSG_IFace;
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ typedef struct {
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
float position[3];
|
||||
float position[3];
|
||||
} CSG_IVertex;
|
||||
|
||||
/**
|
||||
|
@@ -135,10 +135,10 @@ static bool Carve_checkEdgeFaceIntersections(carve::csg::Intersections &intersec
|
||||
|
||||
static inline bool Carve_facesAreCoplanar(const MeshSet<3>::face_t *a, const MeshSet<3>::face_t *b)
|
||||
{
|
||||
carve::geom3d::Ray temp;
|
||||
// XXX: Find a better definition. This may be a source of problems
|
||||
// if floating point inaccuracies cause an incorrect answer.
|
||||
return !carve::geom3d::planeIntersection(a->plane, b->plane, temp);
|
||||
carve::geom3d::Ray temp;
|
||||
// XXX: Find a better definition. This may be a source of problems
|
||||
// if floating point inaccuracies cause an incorrect answer.
|
||||
return !carve::geom3d::planeIntersection(a->plane, b->plane, temp);
|
||||
}
|
||||
|
||||
static bool Carve_checkMeshSetInterseciton_do(carve::csg::Intersections &intersections,
|
||||
|
@@ -35,6 +35,8 @@ set(INC_SYS
|
||||
set(SRC
|
||||
CTR_HashedPtr.h
|
||||
CTR_Map.h
|
||||
CTR_TaggedIndex.h
|
||||
CTR_TaggedSetOps.h
|
||||
)
|
||||
|
||||
# infact nothing to compile!
|
||||
|
@@ -29,7 +29,7 @@ if env['WITH_BF_CYCLES_CUDA_BINARIES']:
|
||||
incs.extend('. bvh render device kernel kernel/osl kernel/svm util subd'.split())
|
||||
incs.extend('#intern/guardedalloc #source/blender/makesrna #source/blender/makesdna'.split())
|
||||
incs.extend('#source/blender/blenloader ../../source/blender/makesrna/intern'.split())
|
||||
incs.extend('#extern/glew/include'.split())
|
||||
incs.extend('#extern/glew/include #intern/mikktspace'.split())
|
||||
incs.append(cycles['BF_OIIO_INC'])
|
||||
incs.append(cycles['BF_BOOST_INC'])
|
||||
incs.append(cycles['BF_PYTHON_INC'])
|
||||
|
@@ -7,6 +7,7 @@ set(INC
|
||||
../util
|
||||
../subd
|
||||
../../guardedalloc
|
||||
../../mikktspace
|
||||
../../../source/blender/makesdna
|
||||
../../../source/blender/makesrna
|
||||
../../../source/blender/blenloader
|
||||
@@ -38,6 +39,7 @@ set(ADDON_FILES
|
||||
addon/__init__.py
|
||||
addon/engine.py
|
||||
addon/enums.py
|
||||
addon/osl.py
|
||||
addon/presets.py
|
||||
addon/properties.py
|
||||
addon/ui.py
|
||||
|
@@ -71,6 +71,13 @@ class CyclesRender(bpy.types.RenderEngine):
|
||||
def view_draw(self, context):
|
||||
engine.draw(self, context.region, context.space_data, context.region_data)
|
||||
|
||||
def update_script_node(self, node):
|
||||
if engine.with_osl():
|
||||
from . import osl
|
||||
osl.update_script_node(node, self.report)
|
||||
else:
|
||||
self.report({'ERROR'}, "OSL support disabled in this build.")
|
||||
|
||||
|
||||
def register():
|
||||
properties.register()
|
||||
@@ -84,3 +91,4 @@ def unregister():
|
||||
properties.unregister()
|
||||
presets.unregister()
|
||||
bpy.utils.unregister_module(__name__)
|
||||
|
||||
|
@@ -83,3 +83,4 @@ def available_devices():
|
||||
def with_osl():
|
||||
import _cycles
|
||||
return _cycles.with_osl
|
||||
|
||||
|
@@ -60,3 +60,4 @@ panorama_types = (
|
||||
('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"),
|
||||
('FISHEYE_EQUISOLID', "Fisheye Equisolid", "Similar to most fisheye modern lens, take sensor dimensions into consideration"),
|
||||
)
|
||||
|
||||
|
127
intern/cycles/blender/addon/osl.py
Normal file
127
intern/cycles/blender/addon/osl.py
Normal file
@@ -0,0 +1,127 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy, _cycles, os, tempfile
|
||||
|
||||
# compile .osl file with given filepath to temporary .oso file
|
||||
def osl_compile(input_path, report):
|
||||
output_file = tempfile.NamedTemporaryFile(mode='w', suffix=".oso", delete=False)
|
||||
output_path = output_file.name
|
||||
output_file.close()
|
||||
|
||||
ok = _cycles.osl_compile(input_path, output_path)
|
||||
|
||||
if ok:
|
||||
report({'INFO'}, "OSL shader compilation succeeded")
|
||||
|
||||
return ok, output_path
|
||||
|
||||
# compile and update shader script node
|
||||
def update_script_node(node, report):
|
||||
import os, shutil
|
||||
|
||||
if node.mode == 'EXTERNAL':
|
||||
# compile external script file
|
||||
script_path = bpy.path.abspath(node.filepath, library=node.id_data.library)
|
||||
script_path_noext, script_ext = os.path.splitext(script_path)
|
||||
|
||||
if script_ext == ".oso":
|
||||
# it's a .oso file, no need to compile
|
||||
ok, oso_path = True, script_path
|
||||
oso_file_remove = False
|
||||
elif script_ext == ".osl":
|
||||
# compile .osl file
|
||||
ok, oso_path = osl_compile(script_path, report)
|
||||
oso_file_remove = True
|
||||
|
||||
if ok:
|
||||
# copy .oso from temporary path to .osl directory
|
||||
dst_path = script_path_noext + ".oso"
|
||||
try:
|
||||
shutil.copy2(oso_path, dst_path)
|
||||
except:
|
||||
report({'ERROR'}, "Failed to write .oso file next to external .osl file at " + dst_path)
|
||||
elif os.path.dirname(node.filepath) == "":
|
||||
# module in search path
|
||||
oso_path = node.filepath
|
||||
oso_file_remove = False
|
||||
ok = True
|
||||
else:
|
||||
# unknown
|
||||
report({'ERROR'}, "External shader script must have .osl or .oso extension, or be a module name")
|
||||
ok = False
|
||||
|
||||
if ok:
|
||||
node.bytecode = ""
|
||||
node.bytecode_hash = ""
|
||||
|
||||
elif node.mode == 'INTERNAL' and node.script:
|
||||
# internal script, we will store bytecode in the node
|
||||
script = node.script
|
||||
osl_path = bpy.path.abspath(script.filepath, library=script.library)
|
||||
|
||||
if script.is_in_memory or script.is_dirty or script.is_modified or not os.path.exists(osl_path):
|
||||
# write text datablock contents to temporary file
|
||||
osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=True)
|
||||
osl_file.write(script.as_string())
|
||||
osl_file.flush()
|
||||
ok, oso_path = osl_compile(osl_file.name, report)
|
||||
oso_file_remove = False
|
||||
osl_file.close()
|
||||
else:
|
||||
# compile text datablock from disk directly
|
||||
ok, oso_path = osl_compile(osl_path, report)
|
||||
oso_file_remove = False
|
||||
|
||||
if ok:
|
||||
# read bytecode
|
||||
try:
|
||||
oso = open(oso_path, 'r')
|
||||
node.bytecode = oso.read()
|
||||
oso.close()
|
||||
except:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
report({'ERROR'}, "Can't read OSO bytecode to store in node at %r" % oso_path)
|
||||
ok = False
|
||||
|
||||
else:
|
||||
report({'WARNING'}, "No text or file specified in node, nothing to compile")
|
||||
return
|
||||
|
||||
if ok:
|
||||
# now update node with new sockets
|
||||
ok = _cycles.osl_update_node(node.id_data.as_pointer(), node.as_pointer(), oso_path)
|
||||
|
||||
if not ok:
|
||||
report({'ERROR'}, "OSL query failed to open " + oso_path)
|
||||
else:
|
||||
report({'ERROR'}, "OSL script compilation failed, see console for errors")
|
||||
|
||||
# remove temporary oso file
|
||||
if oso_file_remove:
|
||||
try:
|
||||
os.remove(oso_path)
|
||||
except:
|
||||
pass
|
||||
|
||||
return ok
|
||||
|
@@ -29,32 +29,138 @@
|
||||
|
||||
#include "util_foreach.h"
|
||||
|
||||
#include "mikktspace.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
/* Find/Add */
|
||||
/* Tangent Space */
|
||||
|
||||
static float3 tangent_from_triangle(float3 v0, float3 v1, float3 v2, float3 tx0, float3 tx1, float3 tx2)
|
||||
{
|
||||
float3 duv1 = tx2 - tx0;
|
||||
float3 duv2 = tx2 - tx1;
|
||||
float3 dp1 = v2 - v0;
|
||||
float3 dp2 = v2 - v1;
|
||||
float det = duv1[0] * duv2[1] - duv1[1] * duv2[0];
|
||||
|
||||
if(det != 0.0f) {
|
||||
return normalize(dp1 * duv2[1] - dp2 * duv1[1]);
|
||||
struct MikkUserData {
|
||||
MikkUserData(const BL::Mesh mesh_, const BL::MeshTextureFaceLayer layer_, int num_faces_)
|
||||
: mesh(mesh_), layer(layer_), num_faces(num_faces_)
|
||||
{
|
||||
tangent.resize(num_faces*4);
|
||||
}
|
||||
else {
|
||||
/* give back a sane default, using a valid edge as a fallback */
|
||||
float3 edge = v1 - v0;
|
||||
|
||||
if(len(edge) == 0.0f)
|
||||
edge = v2 - v0;
|
||||
BL::Mesh mesh;
|
||||
BL::MeshTextureFaceLayer layer;
|
||||
int num_faces;
|
||||
vector<float4> tangent;
|
||||
};
|
||||
|
||||
return normalize(edge);
|
||||
static int mikk_get_num_faces(const SMikkTSpaceContext *context)
|
||||
{
|
||||
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
|
||||
return userdata->num_faces;
|
||||
}
|
||||
|
||||
static int mikk_get_num_verts_of_face(const SMikkTSpaceContext *context, const int face_num)
|
||||
{
|
||||
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
|
||||
BL::MeshTessFace f = userdata->mesh.tessfaces[face_num];
|
||||
int4 vi = get_int4(f.vertices_raw());
|
||||
|
||||
return (vi[3] == 0)? 3: 4;
|
||||
}
|
||||
|
||||
static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], const int face_num, const int vert_num)
|
||||
{
|
||||
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
|
||||
BL::MeshTessFace f = userdata->mesh.tessfaces[face_num];
|
||||
int4 vi = get_int4(f.vertices_raw());
|
||||
BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]];
|
||||
float3 vP = get_float3(v.co());
|
||||
|
||||
P[0] = vP.x;
|
||||
P[1] = vP.y;
|
||||
P[2] = vP.z;
|
||||
}
|
||||
|
||||
static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num)
|
||||
{
|
||||
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
|
||||
BL::MeshTextureFace tf = userdata->layer.data[face_num];
|
||||
float3 tfuv;
|
||||
|
||||
if(vert_num == 0)
|
||||
tfuv = get_float3(tf.uv1());
|
||||
else if(vert_num == 1)
|
||||
tfuv = get_float3(tf.uv2());
|
||||
else if(vert_num == 2)
|
||||
tfuv = get_float3(tf.uv3());
|
||||
else
|
||||
tfuv = get_float3(tf.uv4());
|
||||
|
||||
uv[0] = tfuv.x;
|
||||
uv[1] = tfuv.y;
|
||||
}
|
||||
|
||||
static void mikk_get_normal(const SMikkTSpaceContext *context, float N[3], const int face_num, const int vert_num)
|
||||
{
|
||||
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
|
||||
BL::MeshTessFace f = userdata->mesh.tessfaces[face_num];
|
||||
int4 vi = get_int4(f.vertices_raw());
|
||||
BL::MeshVertex v = userdata->mesh.vertices[vi[vert_num]];
|
||||
float3 vN = get_float3(v.normal());
|
||||
|
||||
N[0] = vN.x;
|
||||
N[1] = vN.y;
|
||||
N[2] = vN.z;
|
||||
}
|
||||
|
||||
static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const float T[], const float sign, const int face, const int vert)
|
||||
{
|
||||
MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
|
||||
|
||||
userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
|
||||
}
|
||||
|
||||
static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts)
|
||||
{
|
||||
/* setup userdata */
|
||||
MikkUserData userdata(b_mesh, b_layer, nverts.size());
|
||||
|
||||
/* setup interface */
|
||||
SMikkTSpaceInterface interface;
|
||||
memset(&interface, 0, sizeof(interface));
|
||||
interface.m_getNumFaces = mikk_get_num_faces;
|
||||
interface.m_getNumVerticesOfFace = mikk_get_num_verts_of_face;
|
||||
interface.m_getPosition = mikk_get_position;
|
||||
interface.m_getTexCoord = mikk_get_texture_coordinate;
|
||||
interface.m_getNormal = mikk_get_normal;
|
||||
interface.m_setTSpaceBasic = mikk_set_tangent_space;
|
||||
|
||||
/* setup context */
|
||||
SMikkTSpaceContext context;
|
||||
memset(&context, 0, sizeof(context));
|
||||
context.m_pUserData = &userdata;
|
||||
context.m_pInterface = &interface;
|
||||
|
||||
/* compute tangents */
|
||||
genTangSpaceDefault(&context);
|
||||
|
||||
/* create attribute */
|
||||
/* todo: create float4 attribute for sign */
|
||||
Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent"));
|
||||
float3 *tangent = attr->data_float3();
|
||||
|
||||
for (int i = 0; i < nverts.size(); i++) {
|
||||
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
|
||||
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]);
|
||||
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]);
|
||||
tangent += 3;
|
||||
|
||||
if(nverts[i] == 4) {
|
||||
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
|
||||
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]);
|
||||
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]);
|
||||
tangent += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create Mesh */
|
||||
|
||||
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
|
||||
{
|
||||
/* create vertices */
|
||||
@@ -167,54 +273,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
|
||||
if(!l->active_render())
|
||||
continue;
|
||||
|
||||
Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent"));
|
||||
|
||||
/* compute average tangents per vertex */
|
||||
float3 *tangents = attr->data_float3();
|
||||
memset(tangents, 0, sizeof(float3)*mesh->verts.size());
|
||||
|
||||
BL::MeshTextureFaceLayer::data_iterator t;
|
||||
|
||||
size_t fi = 0; /* face index */
|
||||
b_mesh.tessfaces.begin(f);
|
||||
for(l->data.begin(t); t != l->data.end() && f != b_mesh.tessfaces.end(); ++t, ++fi, ++f) {
|
||||
int4 vi = get_int4(f->vertices_raw());
|
||||
|
||||
float3 tx0 = get_float3(t->uv1());
|
||||
float3 tx1 = get_float3(t->uv2());
|
||||
float3 tx2 = get_float3(t->uv3());
|
||||
|
||||
float3 v0 = mesh->verts[vi[0]];
|
||||
float3 v1 = mesh->verts[vi[1]];
|
||||
float3 v2 = mesh->verts[vi[2]];
|
||||
|
||||
/* calculate tangent for the triangle;
|
||||
* get vertex positions, and find change in position with respect
|
||||
* to the texture coords in the first texture coord dimension */
|
||||
float3 tangent0 = tangent_from_triangle(v0, v1, v2, tx0, tx1, tx2);
|
||||
|
||||
if(nverts[fi] == 4) {
|
||||
/* quad tangent */
|
||||
float3 tx3 = get_float3(t->uv4());
|
||||
float3 v3 = mesh->verts[vi[3]];
|
||||
float3 tangent1 = tangent_from_triangle(v0, v2, v3, tx0, tx2, tx3);
|
||||
|
||||
tangents[vi[0]] += 0.5f*(tangent0 + tangent1);
|
||||
tangents[vi[1]] += tangent0;
|
||||
tangents[vi[2]] += 0.5f*(tangent0 + tangent1);
|
||||
tangents[vi[3]] += tangent1;
|
||||
}
|
||||
else {
|
||||
/* triangle tangent */
|
||||
tangents[vi[0]] += tangent0;
|
||||
tangents[vi[1]] += tangent0;
|
||||
tangents[vi[2]] += tangent0;
|
||||
}
|
||||
}
|
||||
|
||||
/* normalize tangent vectors */
|
||||
for(int i = 0; i < mesh->verts.size(); i++)
|
||||
tangents[i] = normalize(tangents[i]);
|
||||
mikk_compute_tangents(b_mesh, *l, mesh, nverts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +410,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated)
|
||||
create_mesh(scene, mesh, b_mesh, used_shaders);
|
||||
|
||||
/* free derived mesh */
|
||||
object_remove_mesh(b_data, b_mesh);
|
||||
b_data.meshes.remove(b_mesh);
|
||||
}
|
||||
|
||||
/* displacement method */
|
||||
@@ -409,7 +468,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion)
|
||||
mesh->attributes.remove(std);
|
||||
|
||||
/* free derived mesh */
|
||||
object_remove_mesh(b_data, b_mesh);
|
||||
b_data.meshes.remove(b_mesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -330,10 +330,10 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
|
||||
int num_particles = object_count_particles(*b_ob);
|
||||
|
||||
if(b_ob->is_duplicator()) {
|
||||
hide = true; /* duplicators hidden by default */
|
||||
hide = true; /* duplicators hidden by default */
|
||||
|
||||
/* dupli objects */
|
||||
object_create_duplilist(*b_ob, b_scene);
|
||||
b_ob->dupli_list_create(b_scene, 2);
|
||||
|
||||
BL::Object::dupli_list_iterator b_dup;
|
||||
int b_index = 0;
|
||||
@@ -361,10 +361,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
|
||||
++b_index;
|
||||
}
|
||||
|
||||
object_free_duplilist(*b_ob);
|
||||
b_ob->dupli_list_clear();
|
||||
}
|
||||
|
||||
|
||||
/* sync particles and check if we should render or hide particle emitter */
|
||||
BL::Object::particle_systems_iterator b_psys;
|
||||
for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
|
||||
@@ -422,7 +421,7 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override)
|
||||
int frame = b_scene.frame_current();
|
||||
|
||||
for(int motion = -1; motion <= 1; motion += 2) {
|
||||
scene_frame_set(b_scene, frame + motion);
|
||||
b_scene.frame_set(frame + motion, 0.0f);
|
||||
|
||||
/* camera object */
|
||||
if(b_cam)
|
||||
@@ -432,7 +431,7 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override)
|
||||
sync_objects(b_v3d, motion);
|
||||
}
|
||||
|
||||
scene_frame_set(b_scene, frame);
|
||||
b_scene.frame_set(frame, 0.0f);
|
||||
|
||||
/* tag camera for motion update */
|
||||
if(scene->camera->motion_modified(prevcam))
|
||||
|
@@ -24,9 +24,17 @@
|
||||
#include "blender_session.h"
|
||||
|
||||
#include "util_foreach.h"
|
||||
#include "util_md5.h"
|
||||
#include "util_opengl.h"
|
||||
#include "util_path.h"
|
||||
|
||||
#ifdef WITH_OSL
|
||||
#include "osl.h"
|
||||
|
||||
#include <OSL/oslquery.h>
|
||||
#include <OSL/oslconfig.h>
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
static PyObject *init_func(PyObject *self, PyObject *args)
|
||||
@@ -163,6 +171,170 @@ static PyObject *available_devices_func(PyObject *self, PyObject *args)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WITH_OSL
|
||||
static PyObject *osl_update_node_func(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *pynodegroup, *pynode;
|
||||
const char *filepath = NULL;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "OOs", &pynodegroup, &pynode, &filepath))
|
||||
return NULL;
|
||||
|
||||
/* RNA */
|
||||
PointerRNA nodeptr;
|
||||
RNA_pointer_create((ID*)PyLong_AsVoidPtr(pynodegroup), &RNA_ShaderNodeScript, (void*)PyLong_AsVoidPtr(pynode), &nodeptr);
|
||||
BL::ShaderNodeScript b_node(nodeptr);
|
||||
|
||||
/* update bytecode hash */
|
||||
string bytecode = b_node.bytecode();
|
||||
|
||||
if(!bytecode.empty()) {
|
||||
MD5Hash md5;
|
||||
md5.append((const uint8_t*)bytecode.c_str(), bytecode.size());
|
||||
b_node.bytecode_hash(md5.get_hex().c_str());
|
||||
}
|
||||
else
|
||||
b_node.bytecode_hash("");
|
||||
|
||||
/* query from file path */
|
||||
OSL::OSLQuery query;
|
||||
|
||||
if(!OSLShaderManager::osl_query(query, filepath))
|
||||
Py_RETURN_FALSE;
|
||||
|
||||
/* add new sockets from parameters */
|
||||
set<void*> used_sockets;
|
||||
|
||||
for(int i = 0; i < query.nparams(); i++) {
|
||||
const OSL::OSLQuery::Parameter *param = query.getparam(i);
|
||||
|
||||
/* skip unsupported types */
|
||||
if(param->varlenarray || param->isstruct || param->type.arraylen > 1)
|
||||
continue;
|
||||
|
||||
/* determine socket type */
|
||||
BL::NodeSocket::type_enum socket_type;
|
||||
float default_float4[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
float default_float = 0.0f;
|
||||
int default_int = 0;
|
||||
|
||||
if(param->isclosure) {
|
||||
socket_type = BL::NodeSocket::type_SHADER;
|
||||
}
|
||||
else if(param->type.vecsemantics == TypeDesc::COLOR) {
|
||||
socket_type = BL::NodeSocket::type_RGBA;
|
||||
|
||||
if(param->validdefault) {
|
||||
default_float4[0] = param->fdefault[0];
|
||||
default_float4[1] = param->fdefault[1];
|
||||
default_float4[2] = param->fdefault[2];
|
||||
}
|
||||
}
|
||||
else if(param->type.vecsemantics == TypeDesc::POINT ||
|
||||
param->type.vecsemantics == TypeDesc::VECTOR ||
|
||||
param->type.vecsemantics == TypeDesc::NORMAL) {
|
||||
socket_type = BL::NodeSocket::type_VECTOR;
|
||||
|
||||
if(param->validdefault) {
|
||||
default_float4[0] = param->fdefault[0];
|
||||
default_float4[1] = param->fdefault[1];
|
||||
default_float4[2] = param->fdefault[2];
|
||||
}
|
||||
}
|
||||
else if(param->type.aggregate == TypeDesc::SCALAR) {
|
||||
if(param->type.basetype == TypeDesc::INT) {
|
||||
socket_type = BL::NodeSocket::type_INT;
|
||||
if(param->validdefault)
|
||||
default_int = param->idefault[0];
|
||||
}
|
||||
else if(param->type.basetype == TypeDesc::FLOAT) {
|
||||
socket_type = BL::NodeSocket::type_VALUE;
|
||||
if(param->validdefault)
|
||||
default_float = param->fdefault[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
/* find socket socket */
|
||||
BL::NodeSocket b_sock = b_node.find_socket(param->name.c_str(), param->isoutput);
|
||||
|
||||
/* remove if type no longer matches */
|
||||
if(b_sock && b_sock.type() != socket_type) {
|
||||
b_node.remove_socket(b_sock);
|
||||
b_sock = BL::NodeSocket(PointerRNA_NULL);
|
||||
}
|
||||
|
||||
/* create new socket */
|
||||
if(!b_sock) {
|
||||
b_sock = b_node.add_socket(param->name.c_str(), socket_type, param->isoutput);
|
||||
|
||||
/* set default value */
|
||||
if(socket_type == BL::NodeSocket::type_VALUE) {
|
||||
BL::NodeSocketFloatNone b_float_sock(b_sock.ptr);
|
||||
b_float_sock.default_value(default_float);
|
||||
}
|
||||
else if(socket_type == BL::NodeSocket::type_INT) {
|
||||
BL::NodeSocketIntNone b_int_sock(b_sock.ptr);
|
||||
b_int_sock.default_value(default_int);
|
||||
}
|
||||
else if(socket_type == BL::NodeSocket::type_RGBA) {
|
||||
BL::NodeSocketRGBA b_rgba_sock(b_sock.ptr);
|
||||
b_rgba_sock.default_value(default_float4);
|
||||
}
|
||||
else if(socket_type == BL::NodeSocket::type_VECTOR) {
|
||||
BL::NodeSocketVectorNone b_vector_sock(b_sock.ptr);
|
||||
b_vector_sock.default_value(default_float4);
|
||||
}
|
||||
}
|
||||
|
||||
used_sockets.insert(b_sock.ptr.data);
|
||||
}
|
||||
|
||||
/* remove unused parameters */
|
||||
bool removed;
|
||||
|
||||
do {
|
||||
BL::Node::inputs_iterator b_input;
|
||||
BL::Node::outputs_iterator b_output;
|
||||
|
||||
removed = false;
|
||||
|
||||
for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) {
|
||||
if(used_sockets.find(b_input->ptr.data) == used_sockets.end()) {
|
||||
b_node.remove_socket(*b_input);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) {
|
||||
if(used_sockets.find(b_output->ptr.data) == used_sockets.end()) {
|
||||
b_node.remove_socket(*b_output);
|
||||
removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(removed);
|
||||
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
|
||||
static PyObject *osl_compile_func(PyObject *self, PyObject *args)
|
||||
{
|
||||
const char *inputfile = NULL, *outputfile = NULL;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "ss", &inputfile, &outputfile))
|
||||
return NULL;
|
||||
|
||||
/* return */
|
||||
if(!OSLShaderManager::osl_compile(inputfile, outputfile))
|
||||
Py_RETURN_FALSE;
|
||||
|
||||
Py_RETURN_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static PyMethodDef methods[] = {
|
||||
{"init", init_func, METH_VARARGS, ""},
|
||||
{"create", create_func, METH_VARARGS, ""},
|
||||
@@ -170,6 +342,10 @@ static PyMethodDef methods[] = {
|
||||
{"render", render_func, METH_O, ""},
|
||||
{"draw", draw_func, METH_VARARGS, ""},
|
||||
{"sync", sync_func, METH_O, ""},
|
||||
#ifdef WITH_OSL
|
||||
{"osl_update_node", osl_update_node_func, METH_VARARGS, ""},
|
||||
{"osl_compile", osl_compile_func, METH_VARARGS, ""},
|
||||
#endif
|
||||
{"available_devices", available_devices_func, METH_NOARGS, ""},
|
||||
{NULL, NULL, 0, NULL},
|
||||
};
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include "graph.h"
|
||||
#include "light.h"
|
||||
#include "nodes.h"
|
||||
#include "osl.h"
|
||||
#include "scene.h"
|
||||
#include "shader.h"
|
||||
|
||||
@@ -43,6 +44,7 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default
|
||||
for(size_t i = 0; i < scene->shaders.size(); i++) {
|
||||
if(scene->shaders[i] == shader) {
|
||||
used_shaders.push_back(i);
|
||||
scene->shaders[i]->tag_used(scene);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -158,7 +160,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map
|
||||
mapping->max = get_float3(b_mapping.max());
|
||||
}
|
||||
|
||||
static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNode b_node)
|
||||
static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node)
|
||||
{
|
||||
ShaderNode *node = NULL;
|
||||
|
||||
@@ -412,6 +414,58 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
|
||||
node = new BumpNode();
|
||||
break;
|
||||
}
|
||||
case BL::ShaderNode::type_SCRIPT: {
|
||||
#ifdef WITH_OSL
|
||||
if(scene->params.shadingsystem != SceneParams::OSL)
|
||||
break;
|
||||
|
||||
/* create script node */
|
||||
BL::ShaderNodeScript b_script_node(b_node);
|
||||
OSLScriptNode *script_node = new OSLScriptNode();
|
||||
|
||||
/* Generate inputs/outputs from node sockets
|
||||
*
|
||||
* Note: the node sockets are generated from OSL parameters,
|
||||
* so the names match those of the corresponding parameters exactly.
|
||||
*
|
||||
* Note 2: ShaderInput/ShaderOutput store shallow string copies only!
|
||||
* Socket names must be stored in the extra lists instead. */
|
||||
BL::Node::inputs_iterator b_input;
|
||||
|
||||
for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
|
||||
script_node->input_names.push_back(ustring(b_input->name()));
|
||||
ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type()));
|
||||
set_default_value(input, *b_input);
|
||||
}
|
||||
|
||||
BL::Node::outputs_iterator b_output;
|
||||
|
||||
for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
|
||||
script_node->output_names.push_back(ustring(b_output->name()));
|
||||
script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(b_output->type()));
|
||||
}
|
||||
|
||||
/* load bytecode or filepath */
|
||||
OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
|
||||
string bytecode_hash = b_script_node.bytecode_hash();
|
||||
|
||||
if(!bytecode_hash.empty()) {
|
||||
/* loaded bytecode if not already done */
|
||||
if(!manager->shader_test_loaded(bytecode_hash))
|
||||
manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());
|
||||
|
||||
script_node->bytecode_hash = bytecode_hash;
|
||||
}
|
||||
else {
|
||||
/* set filepath */
|
||||
script_node->filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
|
||||
}
|
||||
|
||||
node = script_node;
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
case BL::ShaderNode::type_TEX_IMAGE: {
|
||||
BL::ShaderNodeTexImage b_image_node(b_node);
|
||||
BL::Image b_image(b_image_node.image());
|
||||
@@ -575,7 +629,7 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL
|
||||
return SocketPair(node_map[b_node.ptr.data], name);
|
||||
}
|
||||
|
||||
static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map)
|
||||
static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map)
|
||||
{
|
||||
/* add nodes */
|
||||
BL::ShaderNodeTree::nodes_iterator b_node;
|
||||
@@ -650,10 +704,10 @@ static void add_nodes(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *grap
|
||||
set_default_value(proxy->inputs[0], b_output->group_socket());
|
||||
}
|
||||
|
||||
add_nodes(b_data, b_scene, graph, b_group_ntree, group_sockmap);
|
||||
add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap);
|
||||
}
|
||||
else {
|
||||
ShaderNode *node = add_node(b_data, b_scene, graph, BL::ShaderNode(*b_node));
|
||||
ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node));
|
||||
|
||||
if(node) {
|
||||
BL::Node::inputs_iterator b_input;
|
||||
@@ -743,7 +797,7 @@ void BlenderSync::sync_materials()
|
||||
PtrSockMap sock_to_node;
|
||||
BL::ShaderNodeTree b_ntree(b_mat->node_tree());
|
||||
|
||||
add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node);
|
||||
add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
|
||||
}
|
||||
else {
|
||||
ShaderNode *closure, *out;
|
||||
@@ -784,7 +838,7 @@ void BlenderSync::sync_world()
|
||||
PtrSockMap sock_to_node;
|
||||
BL::ShaderNodeTree b_ntree(b_world.node_tree());
|
||||
|
||||
add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node);
|
||||
add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
|
||||
}
|
||||
else if(b_world) {
|
||||
ShaderNode *closure, *out;
|
||||
@@ -843,7 +897,7 @@ void BlenderSync::sync_lamps()
|
||||
PtrSockMap sock_to_node;
|
||||
BL::ShaderNodeTree b_ntree(b_lamp->node_tree());
|
||||
|
||||
add_nodes(b_data, b_scene, graph, b_ntree, sock_to_node);
|
||||
add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
|
||||
}
|
||||
else {
|
||||
ShaderNode *closure, *out;
|
||||
|
@@ -39,7 +39,7 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
static inline BL::Mesh object_to_mesh(BL::Object self, BL::Scene scene, bool apply_modifiers, bool render)
|
||||
{
|
||||
return self.to_mesh(NULL, scene, apply_modifiers, (render)? 2: 1);
|
||||
return self.to_mesh(scene, apply_modifiers, (render)? 2: 1);
|
||||
}
|
||||
|
||||
static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size)
|
||||
@@ -52,24 +52,6 @@ static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size
|
||||
}
|
||||
}
|
||||
|
||||
static inline void object_remove_mesh(BL::BlendData data, BL::Mesh mesh)
|
||||
{
|
||||
/* TODO: BlendData.meshes ideally should be also a subclass of BlendDataMeshes */
|
||||
BL::BlendDataMeshes mesh_data(data.ptr);
|
||||
|
||||
mesh_data.remove(NULL, mesh);
|
||||
}
|
||||
|
||||
static inline void object_create_duplilist(BL::Object self, BL::Scene scene)
|
||||
{
|
||||
self.dupli_list_create(NULL, scene, 2);
|
||||
}
|
||||
|
||||
static inline void object_free_duplilist(BL::Object self)
|
||||
{
|
||||
self.dupli_list_clear();
|
||||
}
|
||||
|
||||
static inline bool BKE_object_is_modified(BL::Object self, BL::Scene scene, bool preview)
|
||||
{
|
||||
return self.is_modified(scene, (preview)? (1<<0): (1<<1))? true: false;
|
||||
@@ -88,11 +70,6 @@ static inline string image_user_file_path(BL::ImageUser iuser, BL::Image ima, in
|
||||
return string(filepath);
|
||||
}
|
||||
|
||||
static inline void scene_frame_set(BL::Scene scene, int frame)
|
||||
{
|
||||
scene.frame_set(frame, 0.0f);
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
|
||||
static inline Transform get_transform(BL::Array<float, 16> array)
|
||||
|
@@ -134,6 +134,7 @@ endif()
|
||||
|
||||
if(WITH_CYCLES_OSL)
|
||||
add_subdirectory(osl)
|
||||
add_subdirectory(shaders)
|
||||
endif()
|
||||
|
||||
# CPU module
|
||||
|
@@ -45,13 +45,10 @@ __device_inline float safe_sqrtf(float f)
|
||||
__device int bsdf_microfacet_ggx_setup(ShaderClosure *sc)
|
||||
{
|
||||
float ag = sc->data0;
|
||||
float eta = sc->data1;
|
||||
|
||||
float m_ag = clamp(ag, 1e-4f, 1.0f);
|
||||
float m_eta = eta;
|
||||
|
||||
sc->data0 = m_ag;
|
||||
sc->data1 = m_eta;
|
||||
sc->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
|
||||
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
|
||||
@@ -82,7 +79,6 @@ __device void bsdf_microfacet_ggx_blur(ShaderClosure *sc, float roughness)
|
||||
__device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
|
||||
{
|
||||
float m_ag = sc->data0;
|
||||
//float m_eta = sc->data1;
|
||||
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
float3 N = sc->N;
|
||||
|
||||
@@ -155,7 +151,6 @@ __device float3 bsdf_microfacet_ggx_eval_transmit(const ShaderClosure *sc, const
|
||||
__device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
|
||||
{
|
||||
float m_ag = sc->data0;
|
||||
float m_eta = sc->data1;
|
||||
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
|
||||
float3 N = sc->N;
|
||||
|
||||
@@ -221,6 +216,7 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
float3 dRdx, dRdy, dTdx, dTdy;
|
||||
#endif
|
||||
float m_eta = sc->data1;
|
||||
bool inside;
|
||||
fresnel_dielectric(m_eta, m, I, &R, &T,
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
@@ -274,12 +270,9 @@ __device int bsdf_microfacet_ggx_sample(const ShaderClosure *sc, float3 Ng, floa
|
||||
__device int bsdf_microfacet_beckmann_setup(ShaderClosure *sc)
|
||||
{
|
||||
float ab = sc->data0;
|
||||
float eta = sc->data1;
|
||||
float m_ab = clamp(ab, 1e-4f, 1.0f);
|
||||
float m_eta = eta;
|
||||
|
||||
sc->data0 = m_ab;
|
||||
sc->data1 = m_eta;
|
||||
|
||||
sc->type = CLOSURE_BSDF_MICROFACET_BECKMANN_ID;
|
||||
return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY;
|
||||
@@ -309,7 +302,6 @@ __device void bsdf_microfacet_beckmann_blur(ShaderClosure *sc, float roughness)
|
||||
__device float3 bsdf_microfacet_beckmann_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf)
|
||||
{
|
||||
float m_ab = sc->data0;
|
||||
//float m_eta = sc->data1;
|
||||
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
||||
float3 N = sc->N;
|
||||
|
||||
@@ -386,7 +378,6 @@ __device float3 bsdf_microfacet_beckmann_eval_transmit(const ShaderClosure *sc,
|
||||
__device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf)
|
||||
{
|
||||
float m_ab = sc->data0;
|
||||
float m_eta = sc->data1;
|
||||
int m_refractive = sc->type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID;
|
||||
float3 N = sc->N;
|
||||
|
||||
@@ -456,6 +447,7 @@ __device int bsdf_microfacet_beckmann_sample(const ShaderClosure *sc, float3 Ng,
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
float3 dRdx, dRdy, dTdx, dTdy;
|
||||
#endif
|
||||
float m_eta = sc->data1;
|
||||
bool inside;
|
||||
fresnel_dielectric(m_eta, m, I, &R, &T,
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
|
@@ -68,6 +68,17 @@ __device_inline float3 triangle_normal_MT(KernelGlobals *kg, int tri_index, int
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return 3 triangle vertex locations */
|
||||
__device_inline void triangle_vertices(KernelGlobals *kg, int tri_index, float3 P[3])
|
||||
{
|
||||
/* load triangle vertices */
|
||||
float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
|
||||
|
||||
P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
|
||||
P[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
|
||||
P[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
|
||||
}
|
||||
|
||||
__device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int tri_index, float u, float v)
|
||||
{
|
||||
/* load triangle vertices */
|
||||
|
@@ -34,4 +34,3 @@ include_directories(SYSTEM ${INC_SYS})
|
||||
|
||||
add_library(cycles_kernel_osl ${SRC} ${HEADER_SRC})
|
||||
|
||||
add_subdirectory(nodes)
|
||||
|
@@ -345,6 +345,51 @@ static void set_attribute_float(float f[3], TypeDesc type, bool derivatives, voi
|
||||
}
|
||||
}
|
||||
|
||||
static bool set_attribute_int(int i, TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
if(type.basetype == TypeDesc::INT && type.aggregate == TypeDesc::SCALAR && type.arraylen == 0) {
|
||||
int *ival = (int *)val;
|
||||
ival[0] = i;
|
||||
|
||||
if (derivatives) {
|
||||
ival[1] = 0;
|
||||
ival[2] = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
if(type.vecsemantics == TypeDesc::POINT && type.arraylen >= 3) {
|
||||
float *fval = (float *)val;
|
||||
|
||||
fval[0] = P[0].x;
|
||||
fval[1] = P[0].y;
|
||||
fval[2] = P[0].z;
|
||||
|
||||
fval[3] = P[1].x;
|
||||
fval[4] = P[1].y;
|
||||
fval[5] = P[1].z;
|
||||
|
||||
fval[6] = P[2].x;
|
||||
fval[7] = P[2].y;
|
||||
fval[8] = P[2].z;
|
||||
|
||||
if(type.arraylen > 3)
|
||||
memset(fval + 3*3, 0, sizeof(float)*3*(type.arraylen - 3));
|
||||
if (derivatives)
|
||||
memset(fval + type.arraylen*3, 0, sizeof(float)*2*3*type.arraylen);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr,
|
||||
const TypeDesc& type, bool derivatives, void *val)
|
||||
{
|
||||
@@ -381,43 +426,45 @@ static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivat
|
||||
static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name,
|
||||
TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
/* todo: turn this into hash table + callback once */
|
||||
|
||||
/* Object Attributes */
|
||||
if (name == "std::object_location") {
|
||||
if (name == "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") {
|
||||
else if (name == "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::dupli_generated") {
|
||||
else if (name == "geom:dupli_generated") {
|
||||
float3 fval[3];
|
||||
fval[0] = object_dupli_generated(kg, sd->object);
|
||||
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::dupli_uv") {
|
||||
else if (name == "geom:dupli_uv") {
|
||||
float3 fval[3];
|
||||
fval[0] = object_dupli_uv(kg, sd->object);
|
||||
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::material_index") {
|
||||
else if (name == "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") {
|
||||
else if (name == "object:random") {
|
||||
float fval[3];
|
||||
fval[0] = object_random_number(kg, sd->object);
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
@@ -426,7 +473,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
}
|
||||
|
||||
/* Particle Attributes */
|
||||
else if (name == "std::particle_index") {
|
||||
else if (name == "particle:index") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_index(kg, particle_id);
|
||||
@@ -434,7 +481,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_age") {
|
||||
else if (name == "particle:age") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_age(kg, particle_id);
|
||||
@@ -442,7 +489,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_lifetime") {
|
||||
else if (name == "particle:lifetime") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_lifetime(kg, particle_id);
|
||||
@@ -450,7 +497,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_location") {
|
||||
else if (name == "particle:location") {
|
||||
float3 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_location(kg, particle_id);
|
||||
@@ -459,7 +506,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
return true;
|
||||
}
|
||||
#if 0 /* unsupported */
|
||||
else if (name == "std::particle_rotation") {
|
||||
else if (name == "particle:rotation") {
|
||||
float4 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_rotation(kg, particle_id);
|
||||
@@ -468,7 +515,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
else if (name == "std::particle_size") {
|
||||
else if (name == "particle:size") {
|
||||
float fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_size(kg, particle_id);
|
||||
@@ -476,7 +523,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
set_attribute_float(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_velocity") {
|
||||
else if (name == "particle:velocity") {
|
||||
float3 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_velocity(kg, particle_id);
|
||||
@@ -484,7 +531,7 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
set_attribute_float3(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
else if (name == "std::particle_angular_velocity") {
|
||||
else if (name == "particle:angular_velocity") {
|
||||
float3 fval[3];
|
||||
uint particle_id = object_particle_id(kg, sd->object);
|
||||
fval[0] = particle_angular_velocity(kg, particle_id);
|
||||
@@ -492,7 +539,17 @@ static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ust
|
||||
set_attribute_float3(fval, type, derivatives, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (name == "geom:numpolyvertices") {
|
||||
return set_attribute_int(3, type, derivatives, val);
|
||||
}
|
||||
else if (name == "geom:trianglevertices" || name == "geom:polyvertices") {
|
||||
float3 P[3];
|
||||
triangle_vertices(kg, sd->prim, P);
|
||||
object_position_transform(kg, sd, &P[0]);
|
||||
object_position_transform(kg, sd, &P[1]);
|
||||
object_position_transform(kg, sd, &P[2]);
|
||||
return set_attribute_float3_3(P, type, derivatives, val);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -501,7 +558,7 @@ static bool get_background_attribute(KernelGlobals *kg, ShaderData *sd, ustring
|
||||
TypeDesc type, bool derivatives, void *val)
|
||||
{
|
||||
/* Ray Length */
|
||||
if (name == "std::ray_length") {
|
||||
if (name == "path:ray_length") {
|
||||
float fval[3];
|
||||
fval[0] = sd->ray_length;
|
||||
fval[1] = fval[2] = 0.0; /* derivates set to 0 */
|
||||
|
@@ -76,11 +76,11 @@ set(SRC_OSO
|
||||
# TODO, add a module to compile OSL
|
||||
foreach(_file ${SRC_OSL})
|
||||
set(_OSL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
|
||||
string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE}) # TODO, replace extension only
|
||||
string(REPLACE ".osl" ".oso" _OSO_FILE ${_OSL_FILE})
|
||||
string(REPLACE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} _OSO_FILE ${_OSO_FILE})
|
||||
add_custom_command(
|
||||
OUTPUT ${_OSO_FILE}
|
||||
COMMAND ${OSL_COMPILER} -O2 ${_OSL_FILE}
|
||||
COMMAND ${OSL_COMPILER} -O2 -I"${CMAKE_CURRENT_SOURCE_DIR}" ${_OSL_FILE}
|
||||
DEPENDS ${_OSL_FILE} ${SRC_OSL_HEADERS})
|
||||
list(APPEND SRC_OSO
|
||||
${_OSO_FILE}
|
||||
@@ -94,3 +94,5 @@ add_custom_target(cycles_osl_shaders ALL DEPENDS ${SRC_OSO} ${SRC_OSL_HEADERS})
|
||||
|
||||
# CMAKE_CURRENT_SOURCE_DIR is already included in OSO paths
|
||||
delayed_install("" "${SRC_OSO}" ${CYCLES_INSTALL_PATH}/shader)
|
||||
delayed_install("${CMAKE_CURRENT_SOURCE_DIR}" "${SRC_OSL_HEADERS}" ${CYCLES_INSTALL_PATH}/shader)
|
||||
|
@@ -34,10 +34,10 @@ 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, eta) +
|
||||
BSDF = Color * (Fr * microfacet_beckmann(Normal, Roughness) +
|
||||
(1.0 - Fr) * microfacet_beckmann_refraction(Normal, Roughness, eta));
|
||||
else if (distribution == "GGX")
|
||||
BSDF = Color * (Fr * microfacet_ggx(Normal, Roughness, eta) +
|
||||
BSDF = Color * (Fr * microfacet_ggx(Normal, Roughness) +
|
||||
(1.0 - Fr) * microfacet_ggx_refraction(Normal, Roughness, eta));
|
||||
}
|
||||
|
@@ -29,9 +29,9 @@ shader node_glossy_bsdf(
|
||||
if (distribution == "Sharp")
|
||||
BSDF = Color * reflection(Normal);
|
||||
else if (distribution == "Beckmann")
|
||||
BSDF = Color * microfacet_beckmann(Normal, Roughness, 1.0);
|
||||
BSDF = Color * microfacet_beckmann(Normal, Roughness);
|
||||
else if (distribution == "GGX")
|
||||
BSDF = Color * microfacet_ggx(Normal, Roughness, 1.0);
|
||||
BSDF = Color * microfacet_ggx(Normal, Roughness);
|
||||
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ shader node_light_falloff(
|
||||
{
|
||||
float ray_length = 0.0;
|
||||
float strength = Strength;
|
||||
getattribute("std::ray_length", ray_length);
|
||||
getattribute("path:ray_length", ray_length);
|
||||
|
||||
if (Smooth > 0.0) {
|
||||
float squared = ray_length*ray_length;
|
@@ -36,6 +36,6 @@ shader node_light_path(
|
||||
IsReflectionRay = raytype("reflection");
|
||||
IsTransmissionRay = raytype("refraction");
|
||||
|
||||
getattribute("std::ray_length", RayLength);
|
||||
getattribute("path:ray_length", RayLength);
|
||||
}
|
||||
|
@@ -24,9 +24,9 @@ shader node_object_info(
|
||||
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);
|
||||
getattribute("object:location", Location);
|
||||
getattribute("object:index", ObjectIndex);
|
||||
getattribute("material:index", MaterialIndex);
|
||||
getattribute("object:random", Random);
|
||||
}
|
||||
|
@@ -27,12 +27,12 @@ shader node_particle_info(
|
||||
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);
|
||||
getattribute("particle:index", Index);
|
||||
getattribute("particle:age", Age);
|
||||
getattribute("particle:lifetime", Lifetime);
|
||||
getattribute("particle:location", Location);
|
||||
getattribute("particle:size", Size);
|
||||
getattribute("particle:velocity", Velocity);
|
||||
getattribute("particle:angular_velocity", AngularVelocity);
|
||||
}
|
||||
|
@@ -44,12 +44,12 @@ shader node_texture_coordinate(
|
||||
}
|
||||
else {
|
||||
if (from_dupli) {
|
||||
getattribute("std::dupli_generated", Generated);
|
||||
getattribute("std::dupli_uv", UV);
|
||||
getattribute("geom:dupli_generated", Generated);
|
||||
getattribute("geom:dupli_uv", UV);
|
||||
}
|
||||
else {
|
||||
getattribute("std::generated", Generated);
|
||||
getattribute("std::uv", UV);
|
||||
getattribute("geom:generated", Generated);
|
||||
getattribute("geom:uv", UV);
|
||||
}
|
||||
|
||||
Object = transform("object", P);
|
@@ -27,6 +27,6 @@ shader node_velvet_bsdf(
|
||||
{
|
||||
float sigma = clamp(Sigma, 0.0, 1.0);
|
||||
|
||||
BSDF = Color * ashikhmin_velvet(Normal, sigma, 1.0);
|
||||
BSDF = Color * ashikhmin_velvet(Normal, sigma);
|
||||
}
|
||||
|
@@ -434,81 +434,18 @@ string concat (string a, string b, string c, string d, string e, string f) {
|
||||
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) BUILTIN;
|
||||
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, float eta) BUILTIN;
|
||||
closure color microfacet_ggx(normal N, float ag) BUILTIN;
|
||||
closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
|
||||
closure color microfacet_beckmann(normal N, float ab, float eta) BUILTIN;
|
||||
closure color microfacet_beckmann(normal N, float ab) 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 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;
|
||||
closure color emission(float inner_angle, float outer_angle) BUILTIN;
|
||||
closure color emission(float outer_angle) BUILTIN;
|
||||
closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
|
||||
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, 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;
|
@@ -49,7 +49,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
|
||||
int attr_offset = find_attribute(kg, sd, ATTR_STD_TANGENT);
|
||||
|
||||
if(attr_offset != ATTR_STD_NOT_FOUND) {
|
||||
data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
|
||||
data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
|
||||
object_normal_transform(kg, sd, &data);
|
||||
}
|
||||
else {
|
||||
|
@@ -163,7 +163,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
|
||||
else if(std == ATTR_STD_UV)
|
||||
attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
|
||||
else if(std == ATTR_STD_TANGENT)
|
||||
attr = add(name, TypeDesc::TypeVector, Attribute::VERTEX);
|
||||
attr = add(name, TypeDesc::TypeVector, Attribute::CORNER);
|
||||
else if(std == ATTR_STD_GENERATED)
|
||||
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
|
||||
else if(std == ATTR_STD_POSITION_UNDEFORMED)
|
||||
|
@@ -366,8 +366,8 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att
|
||||
osl_attr.type = TypeDesc::TypeColor;
|
||||
|
||||
if(req.std != ATTR_STD_NONE) {
|
||||
/* if standard attribute, add lookup by std:: name convention */
|
||||
ustring stdname(std::string("std::") + std::string(attribute_standard_name(req.std)));
|
||||
/* if standard attribute, add lookup by geom: name convention */
|
||||
ustring stdname(string("geom:") + string(attribute_standard_name(req.std)));
|
||||
og->attribute_map[i][stdname] = osl_attr;
|
||||
}
|
||||
else if(req.name != ustring()) {
|
||||
|
@@ -2922,5 +2922,25 @@ void SetNormalNode::compile(OSLCompiler& compiler)
|
||||
compiler.add(this, "node_set_normal");
|
||||
}
|
||||
|
||||
/* OSLScriptNode */
|
||||
|
||||
OSLScriptNode::OSLScriptNode()
|
||||
: ShaderNode("osl_script")
|
||||
{
|
||||
}
|
||||
|
||||
void OSLScriptNode::compile(SVMCompiler& compiler)
|
||||
{
|
||||
/* doesn't work for SVM, obviously ... */
|
||||
}
|
||||
|
||||
void OSLScriptNode::compile(OSLCompiler& compiler)
|
||||
{
|
||||
if(!filepath.empty())
|
||||
compiler.add(this, filepath.c_str(), true);
|
||||
else
|
||||
compiler.add(this, bytecode_hash.c_str(), false);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
|
@@ -445,6 +445,18 @@ public:
|
||||
SHADER_NODE_CLASS(SetNormalNode)
|
||||
};
|
||||
|
||||
class OSLScriptNode : public ShaderNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(OSLScriptNode)
|
||||
string filepath;
|
||||
string bytecode_hash;
|
||||
|
||||
/* ShaderInput/ShaderOutput only stores a shallow string copy (const char *)!
|
||||
* The actual socket names have to be stored externally to avoid memory errors. */
|
||||
vector<ustring> input_names;
|
||||
vector<ustring> output_names;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __NODES_H__ */
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "osl_shader.h"
|
||||
|
||||
#include "util_foreach.h"
|
||||
#include "util_md5.h"
|
||||
#include "util_path.h"
|
||||
#include "util_progress.h"
|
||||
|
||||
@@ -46,36 +47,8 @@ OSLShaderManager::OSLShaderManager()
|
||||
{
|
||||
services = new OSLRenderServices();
|
||||
|
||||
/* if we let OSL create it, it leaks */
|
||||
ts = TextureSystem::create(true);
|
||||
ts->attribute("automip", 1);
|
||||
ts->attribute("autotile", 64);
|
||||
|
||||
ss = OSL::ShadingSystem::create(services, ts, &errhandler);
|
||||
ss->attribute("lockgeom", 1);
|
||||
ss->attribute("commonspace", "world");
|
||||
ss->attribute("optimize", 2);
|
||||
//ss->attribute("debug", 1);
|
||||
//ss->attribute("statistics:level", 1);
|
||||
ss->attribute("searchpath:shader", path_get("shader").c_str());
|
||||
|
||||
/* our own ray types */
|
||||
static const char *raytypes[] = {
|
||||
"camera", /* PATH_RAY_CAMERA */
|
||||
"reflection", /* PATH_RAY_REFLECT */
|
||||
"refraction", /* PATH_RAY_TRANSMIT */
|
||||
"diffuse", /* PATH_RAY_DIFFUSE */
|
||||
"glossy", /* PATH_RAY_GLOSSY */
|
||||
"singular", /* PATH_RAY_SINGULAR */
|
||||
"transparent", /* PATH_RAY_TRANSPARENT */
|
||||
"shadow", /* PATH_RAY_SHADOW_OPAQUE */
|
||||
"shadow", /* PATH_RAY_SHADOW_TRANSPARENT */
|
||||
};
|
||||
|
||||
const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]);
|
||||
ss->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
|
||||
|
||||
OSLShader::register_closures(ss);
|
||||
shading_system_init();
|
||||
texture_system_init();
|
||||
}
|
||||
|
||||
OSLShaderManager::~OSLShaderManager()
|
||||
@@ -87,18 +60,14 @@ OSLShaderManager::~OSLShaderManager()
|
||||
|
||||
void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
|
||||
{
|
||||
/* test if we need to update */
|
||||
bool need_update = false;
|
||||
|
||||
foreach(Shader *shader, scene->shaders)
|
||||
if(shader->need_update)
|
||||
need_update = true;
|
||||
|
||||
if(!need_update)
|
||||
return;
|
||||
|
||||
device_free(device, dscene);
|
||||
|
||||
/* determine which shaders are in use */
|
||||
device_update_shaders_used(scene);
|
||||
|
||||
/* create shaders */
|
||||
OSLGlobals *og = (OSLGlobals*)device->osl_memory();
|
||||
|
||||
@@ -110,7 +79,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
|
||||
if(shader->sample_as_light && shader->has_surface_emission)
|
||||
scene->light_manager->need_update = true;
|
||||
|
||||
OSLCompiler compiler((void*)ss);
|
||||
OSLCompiler compiler((void*)this, (void*)ss);
|
||||
compiler.background = (shader == scene->shaders[scene->default_background]);
|
||||
compiler.compile(og, shader);
|
||||
}
|
||||
@@ -126,6 +95,8 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
|
||||
|
||||
foreach(Shader *shader, scene->shaders)
|
||||
shader->need_update = false;
|
||||
|
||||
need_update = false;
|
||||
|
||||
/* set texture system */
|
||||
scene->image_manager->set_osl_texture_system((void*)ts);
|
||||
@@ -151,10 +122,165 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
|
||||
og->background_state.reset();
|
||||
}
|
||||
|
||||
void OSLShaderManager::texture_system_init()
|
||||
{
|
||||
/* if we let OSL create it, it leaks */
|
||||
ts = TextureSystem::create(true);
|
||||
ts->attribute("automip", 1);
|
||||
ts->attribute("autotile", 64);
|
||||
|
||||
/* effectively unlimited for now, until we support proper mipmap lookups */
|
||||
ts->attribute("max_memory_MB", 16384);
|
||||
}
|
||||
|
||||
void OSLShaderManager::shading_system_init()
|
||||
{
|
||||
ss = OSL::ShadingSystem::create(services, ts, &errhandler);
|
||||
ss->attribute("lockgeom", 1);
|
||||
ss->attribute("commonspace", "world");
|
||||
ss->attribute("optimize", 2);
|
||||
//ss->attribute("debug", 1);
|
||||
//ss->attribute("statistics:level", 1);
|
||||
ss->attribute("searchpath:shader", path_get("shader"));
|
||||
|
||||
/* our own ray types */
|
||||
static const char *raytypes[] = {
|
||||
"camera", /* PATH_RAY_CAMERA */
|
||||
"reflection", /* PATH_RAY_REFLECT */
|
||||
"refraction", /* PATH_RAY_TRANSMIT */
|
||||
"diffuse", /* PATH_RAY_DIFFUSE */
|
||||
"glossy", /* PATH_RAY_GLOSSY */
|
||||
"singular", /* PATH_RAY_SINGULAR */
|
||||
"transparent", /* PATH_RAY_TRANSPARENT */
|
||||
"shadow", /* PATH_RAY_SHADOW_OPAQUE */
|
||||
"shadow", /* PATH_RAY_SHADOW_TRANSPARENT */
|
||||
};
|
||||
|
||||
const int nraytypes = sizeof(raytypes)/sizeof(raytypes[0]);
|
||||
ss->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes);
|
||||
|
||||
OSLShader::register_closures(ss);
|
||||
|
||||
loaded_shaders.clear();
|
||||
}
|
||||
|
||||
bool OSLShaderManager::osl_compile(const string& inputfile, const string& outputfile)
|
||||
{
|
||||
vector<string> options;
|
||||
string stdosl_path;
|
||||
|
||||
/* specify output file name */
|
||||
options.push_back("-o");
|
||||
options.push_back(outputfile);
|
||||
|
||||
/* specify standard include path */
|
||||
options.push_back("-I" + path_get("shader"));
|
||||
stdosl_path = path_get("shader/stdosl.h");
|
||||
|
||||
/* compile */
|
||||
OSL::OSLCompiler *compiler = OSL::OSLCompiler::create();
|
||||
bool ok = compiler->compile(inputfile, options, stdosl_path);
|
||||
delete compiler;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool OSLShaderManager::osl_query(OSL::OSLQuery& query, const string& filepath)
|
||||
{
|
||||
string searchpath = path_user_get("shaders");
|
||||
return query.open(filepath, searchpath);
|
||||
}
|
||||
|
||||
static string shader_filepath_hash(const string& filepath, uint64_t modified_time)
|
||||
{
|
||||
/* compute a hash from filepath and modified time to detect changes */
|
||||
MD5Hash md5;
|
||||
md5.append((const uint8_t*)filepath.c_str(), filepath.size());
|
||||
md5.append((const uint8_t*)&modified_time, sizeof(modified_time));
|
||||
|
||||
return md5.get_hex();
|
||||
}
|
||||
|
||||
const char *OSLShaderManager::shader_test_loaded(const string& hash)
|
||||
{
|
||||
set<string>::iterator it = loaded_shaders.find(hash);
|
||||
return (it == loaded_shaders.end())? NULL: it->c_str();
|
||||
}
|
||||
|
||||
const char *OSLShaderManager::shader_load_filepath(string filepath)
|
||||
{
|
||||
size_t len = filepath.size();
|
||||
string extension = filepath.substr(len - 4);
|
||||
uint64_t modified_time = path_modified_time(filepath);
|
||||
|
||||
if(extension == ".osl") {
|
||||
/* .OSL File */
|
||||
string osopath = filepath.substr(0, len - 4) + ".oso";
|
||||
uint64_t oso_modified_time = path_modified_time(osopath);
|
||||
|
||||
/* test if we have loaded the corresponding .OSO already */
|
||||
if(oso_modified_time != 0) {
|
||||
const char *hash = shader_test_loaded(shader_filepath_hash(osopath, oso_modified_time));
|
||||
|
||||
if(hash)
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* autocompile .OSL to .OSO if needed */
|
||||
if(oso_modified_time == 0 || (oso_modified_time < modified_time)) {
|
||||
OSLShaderManager::osl_compile(filepath, osopath);
|
||||
modified_time = path_modified_time(osopath);
|
||||
}
|
||||
else
|
||||
modified_time = oso_modified_time;
|
||||
|
||||
filepath = osopath;
|
||||
}
|
||||
else {
|
||||
if(extension == ".oso") {
|
||||
/* .OSO File, nothing to do */
|
||||
}
|
||||
else if(path_dirname(filepath) == "") {
|
||||
/* .OSO File in search path */
|
||||
filepath = path_join(path_user_get("shaders"), filepath + ".oso");
|
||||
}
|
||||
else {
|
||||
/* unknown file */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* test if we have loaded this .OSO already */
|
||||
const char *hash = shader_test_loaded(shader_filepath_hash(filepath, modified_time));
|
||||
|
||||
if(hash)
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* read oso bytecode from file */
|
||||
string bytecode_hash = shader_filepath_hash(filepath, modified_time);
|
||||
string bytecode;
|
||||
|
||||
if(!path_read_text(filepath, bytecode)) {
|
||||
fprintf(stderr, "Cycles shader graph: failed to read file %s\n", filepath.c_str());
|
||||
loaded_shaders.insert(bytecode_hash); /* to avoid repeat tries */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return shader_load_bytecode(bytecode_hash, bytecode);
|
||||
}
|
||||
|
||||
const char *OSLShaderManager::shader_load_bytecode(const string& hash, const string& bytecode)
|
||||
{
|
||||
ss->LoadMemoryShader(hash.c_str(), bytecode.c_str());
|
||||
|
||||
return loaded_shaders.insert(hash).first->c_str();
|
||||
}
|
||||
|
||||
/* Graph Compiler */
|
||||
|
||||
OSLCompiler::OSLCompiler(void *shadingsys_)
|
||||
OSLCompiler::OSLCompiler(void *manager_, void *shadingsys_)
|
||||
{
|
||||
manager = manager_;
|
||||
shadingsys = shadingsys_;
|
||||
current_type = SHADER_TYPE_SURFACE;
|
||||
current_shader = NULL;
|
||||
@@ -235,10 +361,18 @@ bool OSLCompiler::node_skip_input(ShaderNode *node, ShaderInput *input)
|
||||
return false;
|
||||
}
|
||||
|
||||
void OSLCompiler::add(ShaderNode *node, const char *name)
|
||||
void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
|
||||
{
|
||||
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
|
||||
|
||||
/* load filepath */
|
||||
if(isfilepath) {
|
||||
name = ((OSLShaderManager*)manager)->shader_load_filepath(name);
|
||||
|
||||
if(name == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
/* pass in fixed parameter values */
|
||||
foreach(ShaderInput *input, node->inputs) {
|
||||
if(!input->link) {
|
||||
@@ -507,82 +641,85 @@ void OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph, ShaderType ty
|
||||
|
||||
void OSLCompiler::compile(OSLGlobals *og, Shader *shader)
|
||||
{
|
||||
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
|
||||
ShaderGraph *graph = shader->graph;
|
||||
ShaderNode *output = (graph)? graph->output(): NULL;
|
||||
if(shader->need_update) {
|
||||
OSL::ShadingSystem *ss = (OSL::ShadingSystem*)shadingsys;
|
||||
ShaderGraph *graph = shader->graph;
|
||||
ShaderNode *output = (graph)? graph->output(): NULL;
|
||||
|
||||
/* copy graph for shader with bump mapping */
|
||||
if(output->input("Surface")->link && output->input("Displacement")->link)
|
||||
if(!shader->graph_bump)
|
||||
shader->graph_bump = shader->graph->copy();
|
||||
/* copy graph for shader with bump mapping */
|
||||
if(output->input("Surface")->link && output->input("Displacement")->link)
|
||||
if(!shader->graph_bump)
|
||||
shader->graph_bump = shader->graph->copy();
|
||||
|
||||
/* finalize */
|
||||
shader->graph->finalize(false, true);
|
||||
if(shader->graph_bump)
|
||||
shader->graph_bump->finalize(true, true);
|
||||
/* finalize */
|
||||
shader->graph->finalize(false, true);
|
||||
if(shader->graph_bump)
|
||||
shader->graph_bump->finalize(true, true);
|
||||
|
||||
current_shader = shader;
|
||||
current_shader = shader;
|
||||
|
||||
shader->has_surface = false;
|
||||
shader->has_surface_emission = false;
|
||||
shader->has_surface_transparent = false;
|
||||
shader->has_volume = false;
|
||||
shader->has_displacement = false;
|
||||
shader->has_surface = false;
|
||||
shader->has_surface_emission = false;
|
||||
shader->has_surface_transparent = false;
|
||||
shader->has_volume = false;
|
||||
shader->has_displacement = false;
|
||||
|
||||
/* generate surface shader */
|
||||
if(graph && output->input("Surface")->link) {
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
|
||||
og->surface_state.push_back(ss->state());
|
||||
/* generate surface shader */
|
||||
if(shader->used && graph && output->input("Surface")->link) {
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_SURFACE);
|
||||
shader->osl_surface_ref = ss->state();
|
||||
|
||||
if(shader->graph_bump) {
|
||||
if(shader->graph_bump) {
|
||||
ss->clear_state();
|
||||
compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
|
||||
}
|
||||
|
||||
shader->osl_surface_bump_ref = ss->state();
|
||||
ss->clear_state();
|
||||
|
||||
shader->has_surface = true;
|
||||
}
|
||||
else {
|
||||
shader->osl_surface_ref = OSL::ShadingAttribStateRef();
|
||||
shader->osl_surface_bump_ref = OSL::ShadingAttribStateRef();
|
||||
}
|
||||
|
||||
/* generate volume shader */
|
||||
if(shader->used && graph && output->input("Volume")->link) {
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
|
||||
shader->has_volume = true;
|
||||
|
||||
shader->osl_volume_ref = ss->state();
|
||||
ss->clear_state();
|
||||
compile_type(shader, shader->graph_bump, SHADER_TYPE_SURFACE);
|
||||
og->surface_state.push_back(ss->state());
|
||||
}
|
||||
else
|
||||
og->surface_state.push_back(ss->state());
|
||||
shader->osl_volume_ref = OSL::ShadingAttribStateRef();
|
||||
|
||||
ss->clear_state();
|
||||
|
||||
shader->has_surface = true;
|
||||
}
|
||||
else {
|
||||
og->surface_state.push_back(OSL::ShadingAttribStateRef());
|
||||
og->surface_state.push_back(OSL::ShadingAttribStateRef());
|
||||
/* generate displacement shader */
|
||||
if(shader->used && graph && output->input("Displacement")->link) {
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
|
||||
shader->has_displacement = true;
|
||||
shader->osl_displacement_ref = ss->state();
|
||||
ss->clear_state();
|
||||
}
|
||||
else
|
||||
shader->osl_displacement_ref = OSL::ShadingAttribStateRef();
|
||||
}
|
||||
|
||||
/* generate volume shader */
|
||||
if(graph && output->input("Volume")->link) {
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_VOLUME);
|
||||
shader->has_volume = true;
|
||||
/* push state to array for lookup */
|
||||
og->surface_state.push_back(shader->osl_surface_ref);
|
||||
og->surface_state.push_back(shader->osl_surface_bump_ref);
|
||||
|
||||
og->volume_state.push_back(ss->state());
|
||||
og->volume_state.push_back(ss->state());
|
||||
ss->clear_state();
|
||||
}
|
||||
else {
|
||||
og->volume_state.push_back(OSL::ShadingAttribStateRef());
|
||||
og->volume_state.push_back(OSL::ShadingAttribStateRef());
|
||||
}
|
||||
og->volume_state.push_back(shader->osl_volume_ref);
|
||||
og->volume_state.push_back(shader->osl_volume_ref);
|
||||
|
||||
/* generate displacement shader */
|
||||
if(graph && output->input("Displacement")->link) {
|
||||
compile_type(shader, shader->graph, SHADER_TYPE_DISPLACEMENT);
|
||||
shader->has_displacement = true;
|
||||
|
||||
og->displacement_state.push_back(ss->state());
|
||||
og->displacement_state.push_back(ss->state());
|
||||
ss->clear_state();
|
||||
}
|
||||
else {
|
||||
og->displacement_state.push_back(OSL::ShadingAttribStateRef());
|
||||
og->displacement_state.push_back(OSL::ShadingAttribStateRef());
|
||||
}
|
||||
og->displacement_state.push_back(shader->osl_displacement_ref);
|
||||
og->displacement_state.push_back(shader->osl_displacement_ref);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void OSLCompiler::add(ShaderNode *node, const char *name)
|
||||
void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -20,11 +20,14 @@
|
||||
#define __OSL_H__
|
||||
|
||||
#include "util_set.h"
|
||||
#include "util_string.h"
|
||||
|
||||
#include "shader.h"
|
||||
|
||||
#ifdef WITH_OSL
|
||||
#include <OSL/oslcomp.h>
|
||||
#include <OSL/oslexec.h>
|
||||
#include <OSL/oslquery.h>
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -52,11 +55,24 @@ public:
|
||||
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
|
||||
void device_free(Device *device, DeviceScene *dscene);
|
||||
|
||||
private:
|
||||
/* osl compile and query */
|
||||
static bool osl_compile(const string& inputfile, const string& outputfile);
|
||||
static bool osl_query(OSL::OSLQuery& query, const string& filepath);
|
||||
|
||||
/* shader file loading, all functions return pointer to hash string if found */
|
||||
const char *shader_test_loaded(const string& hash);
|
||||
const char *shader_load_bytecode(const string& hash, const string& bytecode);
|
||||
const char *shader_load_filepath(string filepath);
|
||||
|
||||
protected:
|
||||
void texture_system_init();
|
||||
void shading_system_init();
|
||||
|
||||
OSL::ShadingSystem *ss;
|
||||
OSL::TextureSystem *ts;
|
||||
OSLRenderServices *services;
|
||||
OSL::ErrorHandler errhandler;
|
||||
set<string> loaded_shaders;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -65,10 +81,10 @@ private:
|
||||
|
||||
class OSLCompiler {
|
||||
public:
|
||||
OSLCompiler(void *shadingsys);
|
||||
OSLCompiler(void *manager, void *shadingsys);
|
||||
void compile(OSLGlobals *og, Shader *shader);
|
||||
|
||||
void add(ShaderNode *node, const char *name);
|
||||
void add(ShaderNode *node, const char *name, bool isfilepath = false);
|
||||
|
||||
void parameter(const char *name, float f);
|
||||
void parameter_color(const char *name, float3 f);
|
||||
@@ -104,6 +120,7 @@ private:
|
||||
void generate_nodes(const set<ShaderNode*>& nodes);
|
||||
|
||||
void *shadingsys;
|
||||
void *manager;
|
||||
ShaderType current_type;
|
||||
Shader *current_shader;
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user