diff options
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/CMakeLists.txt | 1 | ||||
-rw-r--r-- | intern/cycles/blender/addon/__init__.py | 6 | ||||
-rw-r--r-- | intern/cycles/blender/addon/engine.py | 1 | ||||
-rw-r--r-- | intern/cycles/blender/addon/presets.py | 17 | ||||
-rw-r--r-- | intern/cycles/blender/addon/properties.py | 27 | ||||
-rw-r--r-- | intern/cycles/blender/addon/ui.py | 25 | ||||
-rw-r--r-- | intern/cycles/blender/addon/version_update.py | 44 | ||||
-rw-r--r-- | intern/cycles/blender/blender_camera.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/blender/blender_curves.cpp | 49 | ||||
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 88 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/blender/blender_python.cpp | 11 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 53 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.h | 3 | ||||
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 15 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 8 |
16 files changed, 275 insertions, 81 deletions
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index ad553fb1d62..e97ad2e71f5 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -44,6 +44,7 @@ set(ADDON_FILES addon/presets.py addon/properties.py addon/ui.py + addon/version_update.py ) add_definitions(${GL_DEFINITIONS}) diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 27d986900c8..d1d27df8dc3 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -31,7 +31,7 @@ bl_info = { import bpy from . import engine - +from . import version_update class CyclesRender(bpy.types.RenderEngine): bl_idname = 'CYCLES' @@ -100,12 +100,16 @@ def register(): presets.register() bpy.utils.register_module(__name__) + bpy.app.handlers.version_update.append(version_update.do_versions) + def unregister(): from . import ui from . import properties from . import presets + bpy.app.handlers.version_update.remove(version_update.do_versions) + ui.unregister() properties.unregister() presets.unregister() diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 21a92a29cfc..18235eca790 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -65,6 +65,7 @@ def bake(engine, obj, pass_type, pixel_array, num_pixels, depth, result): if session is not None: _cycles.bake(engine.session, obj.as_pointer(), pass_type, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer()) + def reset(engine, data, scene): import _cycles data = data.as_pointer() diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py index 9991fdb8e3b..2ec65d7183a 100644 --- a/intern/cycles/blender/addon/presets.py +++ b/intern/cycles/blender/addon/presets.py @@ -33,12 +33,16 @@ class AddPresetIntegrator(AddPresetBase, Operator): preset_values = [ "cycles.max_bounces", "cycles.min_bounces", - "cycles.no_caustics", "cycles.diffuse_bounces", "cycles.glossy_bounces", "cycles.transmission_bounces", + "cycles.volume_bounces", "cycles.transparent_min_bounces", - "cycles.transparent_max_bounces" + "cycles.transparent_max_bounces", + "cycles.use_transparent_shadows", + "cycles.caustics_reflective", + "cycles.caustics_refractive", + "cycles.blur_glossy" ] preset_subdir = "cycles/integrator" @@ -66,10 +70,13 @@ class AddPresetSampling(AddPresetBase, Operator): "cycles.mesh_light_samples", "cycles.subsurface_samples", "cycles.volume_samples", - "cycles.no_caustics", - "cycles.blur_glossy", "cycles.use_square_samples", - "cycles.progressive" + "cycles.progressive", + "cycles.seed", + "cycles.sample_clamp_direct", + "cycles.sample_clamp_indirect", + "cycles.sample_all_lights_direct", + "cycles.sample_all_lights_indirect", ] preset_subdir = "cycles/sampling" diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index b4a1b10f8b4..0ac0e0f091e 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -259,11 +259,18 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=True, ) - cls.no_caustics = BoolProperty( - name="No Caustics", - description="Leave out caustics, resulting in a darker image with less noise", - default=False, + cls.caustics_reflective = BoolProperty( + name="Reflective Caustics", + description="Use reflective caustics, resulting in a brighter image (more noise but added realism)", + default=True, + ) + + cls.caustics_refractive = BoolProperty( + name="Refractive Caustics", + description="Use refractive caustics, resulting in a brighter image (more noise but added realism)", + default=True, ) + cls.blur_glossy = FloatProperty( name="Filter Glossy", description="Adaptively blur glossy shaders after blurry bounces, " @@ -544,6 +551,13 @@ class CyclesCameraSettings(bpy.types.PropertyGroup): subtype='ANGLE', default=0, ) + cls.aperture_ratio = FloatProperty( + name="Aperture Ratio", + description="Distortion to simulate anamorphic lens bokeh", + min=0.01, soft_min=1.0, soft_max=2.0, + default=1.0, + precision=4, + ) cls.panorama_type = EnumProperty( name="Panorama Type", description="Distortion to use for the calculation", @@ -724,6 +738,11 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup): description="Object visibility for shadow rays", default=True, ) + cls.scatter = BoolProperty( + name="Volume Scatter", + description="Object visibility for volume scatter rays", + default=True, + ) @classmethod def unregister(cls): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 35ae8ecb7c1..6e40c42fb2d 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -154,7 +154,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): sub.prop(cscene, "subsurface_samples", text="Subsurface") sub.prop(cscene, "volume_samples", text="Volume") - if cscene.feature_set == 'EXPERIMENTAL' and use_cpu(context): + if use_cpu(context) or cscene.feature_set == 'EXPERIMENTAL': layout.row().prop(cscene, "sampling_pattern", text="Pattern") for rl in scene.render.layers: @@ -210,7 +210,8 @@ class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel): col.separator() - col.prop(cscene, "no_caustics") + col.prop(cscene, "caustics_reflective") + col.prop(cscene, "caustics_refractive") col.prop(cscene, "blur_glossy") col = split.column() @@ -468,6 +469,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel): sub = col.column(align=True) sub.prop(ccam, "aperture_blades", text="Blades") sub.prop(ccam, "aperture_rotation", text="Rotation") + sub.prop(ccam, "aperture_ratio", text="Ratio") class Cycles_PT_context_material(CyclesButtonsPanel, Panel): @@ -617,6 +619,7 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel): flow.prop(visibility, "diffuse") flow.prop(visibility, "glossy") flow.prop(visibility, "transmission") + flow.prop(visibility, "scatter") if ob.type != 'LAMP': flow.prop(visibility, "shadow") @@ -629,7 +632,8 @@ class CYCLES_OT_use_shading_nodes(Operator): @classmethod def poll(cls, context): - return context.material or context.world or context.lamp + return (getattr(context, "material", False) or getattr(context, "world", False) or + getattr(context, "lamp", False)) def execute(self, context): if context.material: @@ -895,6 +899,7 @@ class CyclesWorld_PT_ray_visibility(CyclesButtonsPanel, Panel): flow.prop(visibility, "diffuse") flow.prop(visibility, "glossy") flow.prop(visibility, "transmission") + flow.prop(visibility, "scatter") class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel): @@ -928,7 +933,9 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel): col = split.column() col.label(text="Volume:") - col.prop(cworld, "volume_sampling", text="") + sub = col.column() + sub.active = use_cpu(context) + sub.prop(cworld, "volume_sampling", text="") col.prop(cworld, "homogeneous_volume", text="Homogeneous") @@ -1030,7 +1037,9 @@ class CyclesMaterial_PT_settings(CyclesButtonsPanel, Panel): col = split.column() col.label(text="Volume:") - col.prop(cmat, "volume_sampling", text="") + sub = col.column() + sub.active = use_cpu(context) + sub.prop(cmat, "volume_sampling", text="") col.prop(cmat, "homogeneous_volume", text="Homogeneous") @@ -1244,13 +1253,13 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel): scene = context.scene cscene = scene.cycles cbk = scene.render.bake - + layout.operator("object.bake", icon='RENDER_STILL').type = cscene.bake_type - + col = layout.column() col.prop(cscene, "bake_type") col.separator() - + split = layout.split() col = split.column() diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py new file mode 100644 index 00000000000..6f9509e7d99 --- /dev/null +++ b/intern/cycles/blender/addon/version_update.py @@ -0,0 +1,44 @@ +# +# Copyright 2011-2014 Blender Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License +# + +# <pep8 compliant> + +import bpy + +from bpy.app.handlers import persistent + + +@persistent +def do_versions(self): + # We don't modify startup file because it assumes to + # have all the default values only. + if not bpy.data.is_saved: + return + + if bpy.data.version <= (2, 71, 0): + for scene in bpy.data.scenes: + cscene = scene.cycles + if not cscene.is_property_set("volume_bounces"): + cscene.volume_bounces = 1 + + for scene in bpy.data.scenes: + cscene = scene.cycles + if (cscene.get("no_caustics", False) and + not cscene.is_property_set("caustics_reflective") and + not cscene.is_property_set("caustics_refractive")): + + cscene.caustics_reflective = False + cscene.caustics_refractive = False diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 1a85561c6d5..ce8c64c4819 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -46,6 +46,8 @@ struct BlenderCamera { float2 pixelaspect; + float aperture_ratio; + PanoramaType panorama_type; float fisheye_fov; float fisheye_lens; @@ -167,6 +169,7 @@ static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, boo bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades"); bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation"); bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera); + bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio"); bcam->shift.x = b_camera.shift_x(); bcam->shift.y = b_camera.shift_y(); @@ -328,6 +331,9 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->fisheye_fov = bcam->fisheye_fov; cam->fisheye_lens = bcam->fisheye_lens; + /* anamorphic lens bokeh */ + cam->aperture_ratio = bcam->aperture_ratio; + /* perspective */ cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio); cam->focaldistance = bcam->focaldistance; diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 7b1a8ec0b15..8cfaea59a06 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -15,10 +15,11 @@ */ #include "attribute.h" +#include "camera.h" +#include "curves.h" #include "mesh.h" #include "object.h" #include "scene.h" -#include "curves.h" #include "blender_sync.h" #include "blender_util.h" @@ -39,7 +40,8 @@ bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Parti bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num); bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background); void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData); -void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam); +void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, + float3 RotCam, bool is_ortho); void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution); void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata); void ExportCurveTriangleVcol(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata); @@ -328,7 +330,8 @@ static void set_resolution(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, BL::S } } -void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam) +void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, + float3 RotCam, bool is_ortho) { int vertexno = mesh->verts.size(); int vertexindex = vertexno; @@ -362,7 +365,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC float3 ickey_loc = CData->curvekey_co[CData->curve_firstkey[curve]]; float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.0f); v1 = CData->curvekey_co[CData->curve_firstkey[curve] + 1] - CData->curvekey_co[CData->curve_firstkey[curve]]; - xbasis = normalize(cross(RotCam - ickey_loc,v1)); + if(is_ortho) + xbasis = normalize(cross(RotCam, v1)); + else + xbasis = normalize(cross(RotCam - ickey_loc, v1)); float3 ickey_loc_shfl = ickey_loc - radius * xbasis; float3 ickey_loc_shfr = ickey_loc + radius * xbasis; mesh->verts.push_back(ickey_loc_shfl); @@ -386,7 +392,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotC if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f); - xbasis = normalize(cross(RotCam - ickey_loc,v1)); + if(is_ortho) + xbasis = normalize(cross(RotCam, v1)); + else + xbasis = normalize(cross(RotCam - ickey_loc, v1)); float3 ickey_loc_shfl = ickey_loc - radius * xbasis; float3 ickey_loc_shfr = ickey_loc + radius * xbasis; mesh->verts.push_back(ickey_loc_shfl); @@ -858,20 +867,26 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview); - /* obtain camera parameters */ - BL::Object b_CamOb = b_scene.camera(); - float3 RotCam = make_float3(0.0f, 0.0f, 0.0f); - if(b_CamOb) { - Transform ctfm = get_transform(b_CamOb.matrix_world()); - Transform tfm = get_transform(b_ob.matrix_world()); - Transform itfm = transform_quick_inverse(tfm); - RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w)); - } - /* add hair geometry to mesh */ if(primitive == CURVE_TRIANGLES) { - if(triangle_method == CURVE_CAMERA_TRIANGLES) - ExportCurveTrianglePlanes(mesh, &CData, RotCam); + if(triangle_method == CURVE_CAMERA_TRIANGLES) { + /* obtain camera parameters */ + float3 RotCam; + Camera *camera = scene->camera; + Transform &ctfm = camera->matrix; + if(camera->type == CAMERA_ORTHOGRAPHIC) { + RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z); + } + else { + Transform tfm = get_transform(b_ob.matrix_world()); + Transform itfm = transform_quick_inverse(tfm); + RotCam = transform_point(&itfm, make_float3(ctfm.x.w, + ctfm.y.w, + ctfm.z.w)); + } + bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC; + ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho); + } else { ExportCurveTriangleGeometry(mesh, &CData, resolution); used_res = resolution; diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index e7c18c9706b..a5e4b7bd2ae 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -35,14 +35,14 @@ CCL_NAMESPACE_BEGIN /* Tangent Space */ struct MikkUserData { - MikkUserData(const BL::Mesh mesh_, const BL::MeshTextureFaceLayer layer_, int num_faces_) + MikkUserData(const BL::Mesh mesh_, BL::MeshTextureFaceLayer *layer_, int num_faces_) : mesh(mesh_), layer(layer_), num_faces(num_faces_) { tangent.resize(num_faces*4); } BL::Mesh mesh; - BL::MeshTextureFaceLayer layer; + BL::MeshTextureFaceLayer *layer; int num_faces; vector<float4> tangent; }; @@ -78,26 +78,34 @@ static void mikk_get_position(const SMikkTSpaceContext *context, float P[3], con 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; - - switch (vert_num) { - case 0: - tfuv = get_float3(tf.uv1()); - break; - case 1: - tfuv = get_float3(tf.uv2()); - break; - case 2: - tfuv = get_float3(tf.uv3()); - break; - default: - tfuv = get_float3(tf.uv4()); - break; + if(userdata->layer != NULL) { + BL::MeshTextureFace tf = userdata->layer->data[face_num]; + float3 tfuv; + + switch (vert_num) { + case 0: + tfuv = get_float3(tf.uv1()); + break; + case 1: + tfuv = get_float3(tf.uv2()); + break; + case 2: + tfuv = get_float3(tf.uv3()); + break; + default: + tfuv = get_float3(tf.uv4()); + break; + } + + uv[0] = tfuv.x; + uv[1] = tfuv.y; + } + else { + int vert_idx = userdata->mesh.tessfaces[face_num].vertices()[vert_num]; + float3 orco = + get_float3(userdata->mesh.vertices[vert_idx].undeformed_co()); + map_to_sphere(&uv[0], &uv[1], orco[0], orco[1], orco[2]); } - - 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) @@ -127,7 +135,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa 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, bool need_sign, bool active_render) +static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer *b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render) { /* setup userdata */ MikkUserData userdata(b_mesh, b_layer, nverts.size()); @@ -153,7 +161,11 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la /* create tangent attributes */ Attribute *attr; - ustring name = ustring((string(b_layer.name().c_str()) + ".tangent").c_str()); + ustring name; + if(b_layer != NULL) + name = ustring((string(b_layer->name().c_str()) + ".tangent").c_str()); + else + name = ustring("orco.tangent"); if(active_render) attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name); @@ -167,7 +179,11 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la if(need_sign) { Attribute *attr_sign; - ustring name_sign = ustring((string(b_layer.name().c_str()) + ".tangent_sign").c_str()); + ustring name_sign; + if(b_layer != NULL) + name_sign = ustring((string(b_layer->name().c_str()) + ".tangent_sign").c_str()); + else + name_sign = ustring("orco.tangent_sign"); if(active_render) attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign); @@ -371,7 +387,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< } /* create uv map attributes */ - { + if (b_mesh.tessface_uv_textures.length() != 0) { BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { @@ -416,10 +432,14 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)); - mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render); + mikk_compute_tangents(b_mesh, &(*l), mesh, nverts, need_sign, active_render); } } } + else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) { + bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN); + mikk_compute_tangents(b_mesh, NULL, mesh, nverts, need_sign, true); + } /* for volume objects, create a matrix to transform from object space to * mesh texture space. this does not work with deformations but that can @@ -505,15 +525,16 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri } /* test if we need to sync */ + bool use_mesh_geometry = render_layer.use_surfaces || render_layer.use_hair; Mesh *mesh; if(!mesh_map.sync(&mesh, key)) { - /* if transform was applied to mesh, need full update */ if(object_updated && mesh->transform_applied); /* test if shaders changed, these can be object level so mesh * does not get tagged for recalc */ else if(mesh->used_shaders != used_shaders); + else if(use_mesh_geometry != mesh->geometry_synced); else { /* even if not tagged for recalc, we may need to sync anyway * because the shader needs different mesh attributes */ @@ -540,15 +561,21 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri vector<Mesh::Triangle> oldtriangle = mesh->triangles; /* compares curve_keys rather than strands in order to handle quick hair - * adjustsments in dynamic BVH - other methods could probably do this better*/ + * adjustments in dynamic BVH - other methods could probably do this better*/ vector<float4> oldcurve_keys = mesh->curve_keys; mesh->clear(); mesh->used_shaders = used_shaders; mesh->name = ustring(b_ob_data.name().c_str()); - if(render_layer.use_surfaces || render_layer.use_hair) { - if(preview) + if(use_mesh_geometry) { + /* mesh objects does have special handle in the dependency graph, + * they're ensured to have properly updated. + * + * updating meshes here will end up having derived mesh referencing + * freed data from the blender side. + */ + if(preview && b_ob.type() != BL::Object::type_MESH) b_ob.update_from_editmode(); bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED); @@ -570,6 +597,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri /* free derived mesh */ b_data.meshes.remove(b_mesh); } + mesh->geometry_synced = true; } /* displacement method */ diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 94dec0b8244..1e07c5f9c96 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -82,6 +82,7 @@ static uint object_ray_visibility(BL::Object b_ob) flag |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0; flag |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0; flag |= get_boolean(cvisibility, "shadow")? PATH_RAY_SHADOW: 0; + flag |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0; return flag; } @@ -172,6 +173,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0; light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0; light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0; + light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0; /* tag */ light->tag_update(scene); diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 1d18f564e32..b756d6acdb2 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -179,7 +179,7 @@ static PyObject *bake_func(PyObject *self, PyObject *args) python_thread_state_save(&session->python_thread_state); - session->bake(b_object, pass_type, b_bake_pixel, num_pixels, depth, (float *)b_result); + session->bake(b_object, pass_type, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result); python_thread_state_restore(&session->python_thread_state); @@ -363,7 +363,12 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) /* find socket socket */ BL::NodeSocket b_sock(PointerRNA_NULL); if (param->isoutput) { +#if OSL_LIBRARY_VERSION_CODE < 10500 b_sock = b_node.outputs[param->name]; +#else + b_sock = b_node.outputs[param->name.string()]; +#endif + /* remove if type no longer matches */ if(b_sock && b_sock.bl_idname() != socket_type) { @@ -372,7 +377,11 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) } } else { +#if OSL_LIBRARY_VERSION_CODE < 10500 b_sock = b_node.inputs[param->name]; +#else + b_sock = b_node.inputs[param->name.string()]; +#endif /* remove if type no longer matches */ if(b_sock && b_sock.bl_idname() != socket_type) { diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 0f31e55d60d..4ff3d89f9f1 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -88,6 +88,7 @@ void BlenderSession::create_session() { SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); + bool session_pause = BlenderSync::get_session_pause(b_scene, background); /* reset status/progress */ last_status = ""; @@ -107,15 +108,17 @@ void BlenderSession::create_session() session->scene = scene; session->progress.set_update_callback(function_bind(&BlenderSession::tag_redraw, this)); session->progress.set_cancel_callback(function_bind(&BlenderSession::test_cancel, this)); - session->set_pause(BlenderSync::get_session_pause(b_scene, background)); + session->set_pause(session_pause); /* create sync */ sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress, session_params.device.type == DEVICE_CPU); if(b_v3d) { - /* full data sync */ - sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state); - sync->sync_view(b_v3d, b_rv3d, width, height); + if(session_pause == false) { + /* full data sync */ + sync->sync_view(b_v3d, b_rv3d, width, height); + sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state); + } } else { /* for final render we will do full data sync per render layer, only @@ -492,7 +495,7 @@ static void populate_bake_data(BakeData *data, BL::BakePixel pixel_array, const } } -void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, int num_pixels, int depth, float result[]) +void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float result[]) { ShaderEvalType shader_type = get_shader_type(pass_type); size_t object_index = OBJECT_NONE; @@ -526,6 +529,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + scene->bake_manager->set_shader_limit((size_t)b_engine.tile_x(), (size_t)b_engine.tile_y()); scene->bake_manager->set_baking(true); /* set number of samples */ @@ -554,6 +558,8 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, BL::Bake session->reset(buffer_params, session_params.samples); session->update_scene(); + session->progress.set_update_callback(function_bind(&BlenderSession::update_bake_progress, this)); + scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_data, result); /* free all memory used (host and device), so we wouldn't leave render @@ -625,6 +631,7 @@ void BlenderSession::synchronize() /* on session/scene parameter changes, we recreate session entirely */ SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); + bool session_pause = BlenderSync::get_session_pause(b_scene, background); if(session->params.modified(session_params) || scene->params.modified(scene_params)) @@ -637,12 +644,18 @@ void BlenderSession::synchronize() /* increase samples, but never decrease */ session->set_samples(session_params.samples); - session->set_pause(BlenderSync::get_session_pause(b_scene, background)); + session->set_pause(session_pause); /* copy recalc flags, outside of mutex so we can decide to do the real * synchronization at a later time to not block on running updates */ sync->sync_recalc(); + /* don't do synchronization if on pause */ + if(session_pause) { + tag_update(); + return; + } + /* try to acquire mutex. if we don't want to or can't, come back later */ if(!session->ready_to_reset() || !session->scene->mutex.try_lock()) { tag_update(); @@ -718,10 +731,12 @@ bool BlenderSession::draw(int w, int h) if(reset) { SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); BufferParams buffer_params = BlenderSync::get_buffer_params(b_render, b_scene, b_v3d, b_rv3d, scene->camera, width, height); + bool session_pause = BlenderSync::get_session_pause(b_scene, background); - session->reset(buffer_params, session_params.samples); - - start_resize_time = 0.0; + if(session_pause == false) { + session->reset(buffer_params, session_params.samples); + start_resize_time = 0.0; + } } } else { @@ -765,6 +780,26 @@ void BlenderSession::get_progress(float& progress, double& total_time) progress = 0.0; } +void BlenderSession::update_bake_progress() +{ + float progress; + int sample, samples_per_task, parts_total; + + sample = session->progress.get_sample(); + samples_per_task = scene->bake_manager->num_samples; + parts_total = scene->bake_manager->num_parts; + + if(samples_per_task) + progress = ((float)sample / (float)(parts_total * samples_per_task)); + else + progress = 0.0; + + if(progress != last_progress) { + b_engine.update_progress(progress); + last_progress = progress; + } +} + void BlenderSession::update_status_progress() { string timestatus, status, substatus; diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 0e44493d674..ac685118b3d 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -52,7 +52,7 @@ public: /* offline render */ void render(); - void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, int num_pixels, int depth, float pixels[]); + void bake(BL::Object b_object, const string& pass_type, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]); void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile); void write_render_tile(RenderTile& rtile); @@ -73,6 +73,7 @@ public: void get_progress(float& progress, double& total_time); void test_cancel(); void update_status_progress(); + void update_bake_progress(); bool background; Session *session; diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index 51d8a4da744..7752c1ce1bd 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -572,6 +572,13 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen image->animated = b_image_node.image_user().use_auto_refresh(); image->use_alpha = b_image.use_alpha(); + + /* TODO(sergey): Does not work properly when we change builtin type. */ + if (b_image.is_updated()) { + scene->image_manager->tag_reload_image(image->filename, + image->builtin_data, + (InterpolationType)b_image_node.interpolation()); + } } image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()]; image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()]; @@ -602,6 +609,13 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen } env->use_alpha = b_image.use_alpha(); + + /* TODO(sergey): Does not work properly when we change builtin type. */ + if (b_image.is_updated()) { + scene->image_manager->tag_reload_image(env->filename, + env->builtin_data, + INTERPOLATION_LINEAR); + } } env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()]; env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()]; @@ -1057,6 +1071,7 @@ void BlenderSync::sync_world(bool update_all) visibility |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0; visibility |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0; visibility |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0; + visibility |= get_boolean(cvisibility, "scatter")? PATH_RAY_VOLUME_SCATTER: 0; background->visibility = visibility; } diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 19898bfa573..2ac90b34fd7 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -180,10 +180,12 @@ void BlenderSync::sync_integrator() integrator->volume_max_steps = get_int(cscene, "volume_max_steps"); integrator->volume_step_size = get_float(cscene, "volume_step_size"); - integrator->no_caustics = get_boolean(cscene, "no_caustics"); + integrator->caustics_reflective = get_boolean(cscene, "caustics_reflective"); + integrator->caustics_refractive = get_boolean(cscene, "caustics_refractive"); integrator->filter_glossy = get_float(cscene, "blur_glossy"); integrator->seed = get_int(cscene, "seed"); + integrator->sampling_pattern = (SamplingPattern)RNA_enum_get(&cscene, "sampling_pattern"); integrator->layer_flag = render_layer.layer; @@ -231,10 +233,6 @@ void BlenderSync::sync_integrator() integrator->subsurface_samples = subsurface_samples; integrator->volume_samples = volume_samples; } - - - if(experimental) - integrator->sampling_pattern = (SamplingPattern)RNA_enum_get(&cscene, "sampling_pattern"); if(integrator->modified(previntegrator)) integrator->tag_update(scene); |