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:
Tamito Kajiyama
2012-11-04 02:22:56 +00:00
401 changed files with 5843 additions and 3351 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -83,3 +83,4 @@ def available_devices():
def with_osl():
import _cycles
return _cycles.with_osl

View File

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -134,6 +134,7 @@ endif()
if(WITH_CYCLES_OSL)
add_subdirectory(osl)
add_subdirectory(shaders)
endif()
# CPU module

View File

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

View File

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

View File

@@ -34,4 +34,3 @@ include_directories(SYSTEM ${INC_SYS})
add_library(cycles_kernel_osl ${SRC} ${HEADER_SRC})
add_subdirectory(nodes)

View File

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

View File

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

View File

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

View File

@@ -29,9 +29,9 @@ shader node_glossy_bsdf(
if (distribution == "Sharp")
BSDF = Color * reflection(Normal);
else if (distribution == "Beckmann")
BSDF = Color * microfacet_beckmann(Normal, Roughness, 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);
}

View File

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

View File

@@ -36,6 +36,6 @@ shader node_light_path(
IsReflectionRay = raytype("reflection");
IsTransmissionRay = raytype("refraction");
getattribute("std::ray_length", RayLength);
getattribute("path:ray_length", RayLength);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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