diff options
author | Campbell Barton <ideasman42@gmail.com> | 2014-10-03 17:10:05 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2014-10-03 17:10:05 +0400 |
commit | 65acb7b3ee44befaad0d7744816e52b24f970924 (patch) | |
tree | 019cfcd0e00c4637aa06f1eef04e879ae14788a2 | |
parent | b39b6c7fdaf1827334b9945a3c3383dbf9e78d36 (diff) | |
parent | 4c43fcf791c3c26fe5f729ffe5e96bae2957e88a (diff) |
Merge branch 'master' into dyntopo_holes
24 files changed, 569 insertions, 175 deletions
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 016f6637b3c..ce8c64c4819 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -390,7 +390,6 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override /* sync */ Camera *cam = scene->camera; blender_camera_sync(cam, &bcam, width, height); - scene->camera->use_camera_in_volume = experimental; } void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time) @@ -555,7 +554,6 @@ void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height); blender_camera_sync(scene->camera, &bcam, width, height); - scene->camera->use_camera_in_volume = experimental; } BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height) diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 8eee6a2c79e..07a6eb36a3c 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -260,6 +260,11 @@ public: return data.size(); } + T* get_data() + { + return &data[0]; + } + private: array<T> data; }; diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index a0c59e6cbc0..c6aed1205e0 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -35,139 +35,38 @@ CCL_NAMESPACE_BEGIN -/* Approximate erf and erfinv implementations +/* Approximate erf and erfinv implementations. + * Implementation comes stright from the wikipedia: * - * Adapted from code (C) Copyright John Maddock 2006. - * Use, modification and distribution are subject to the - * Boost Software License, Version 1.0. (See accompanying file - * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ - -ccl_device float approx_erff_impl(float z) -{ - float result; - - if(z < 0.5f) { - if(z < 1e-10f) { - if(z == 0) { - result = 0; - } - else { - float c = 0.0033791670f; - result = z * 1.125f + z * c; - } - } - else { - float Y = 1.044948577f; - - float zz = z * z; - float num = (((-0.007727583f * zz) + -0.050999073f)*zz + -0.338165134f)*zz + 0.083430589f; - float denom = (((0.000370900f * zz) + 0.008585719f)*zz + 0.087522260f)*zz + 0.455004033f; - result = z * (Y + num / denom); - } - } - else if(z < 2.5f) { - if(z < 1.5f) { - float Y = 0.4059357643f; - float fz = z - 0.5f; - - float num = (((0.088890036f * fz) + 0.191003695f)*fz + 0.178114665f)*fz + -0.098090592f; - float denom = (((0.123850974f * fz) + 0.578052804f)*fz + 1.426280048f)*fz + 1.847590709f; - - result = Y + num / denom; - result *= expf(-z * z) / z; - } - else { - float Y = 0.506728172f; - float fz = z - 1.5f; - float num = (((0.017567943f * fz) + 0.043948189f)*fz + 0.038654037f)*fz + -0.024350047f; - float denom = (((0.325732924f * fz) + 0.982403709f)*fz + 1.539914949f)*fz + 1; - - result = Y + num / denom; - result *= expf(-z * z) / z; - } - - result = 1 - result; - } - else { - result = 1; - } - - return result; -} + * http://en.wikipedia.org/wiki/Error_function + * + * Some constants are baked into the code. + */ -ccl_device float approx_erff(float z) +ccl_device_inline float approx_erff(float x) { float s = 1.0f; - - if(z < 0.0f) { + if(x < 0.0f) { s = -1.0f; - z = -z; - } - - return s * approx_erff_impl(z); -} - -ccl_device float approx_erfinvf_impl(float p, float q) -{ - float result = 0; - - if(p <= 0.5f) { - float Y = 0.089131474f; - float g = p * (p + 10); - float num = (((-0.012692614f * p) + 0.033480662f)*p + -0.008368748f)*p + -0.000508781f; - float denom = (((1.562215583f * p) + -1.565745582f)*p + -0.970005043f)*p + 1.0f; - float r = num / denom; - result = g * Y + g * r; + x = -x; } - else if(q >= 0.25f) { - float Y = 2.249481201f; - float g = sqrtf(-2 * logf(q)); - float xs = q - 0.25f; - float num = (((17.644729840f * xs) + 8.370503283f)*xs + 0.105264680f)*xs + -0.202433508f; - float denom = (((-28.660818049f * xs) + 3.971343795f)*xs + 6.242641248f)*xs + 1.0f; - float r = num / denom; - result = g / (Y + r); + /* Such a clamp doesn't give much distortion to the output value + * and gives quite a few of the speedup. + */ + if(x > 3.0f) { + return s; } - else { - float x = sqrtf(-logf(q)); - - if(x < 3) { - float Y = 0.807220458f; - float xs = x - 1.125f; - float num = (((0.387079738f * xs) + 0.117030156f)*xs + -0.163794047f)*xs + -0.131102781f; - float denom = (((4.778465929f * xs) + 5.381683457f)*xs + 3.466254072f)*xs + 1.0f; - float R = num / denom; - result = Y * x + R * x; - } - else { - float Y = 0.939955711f; - float xs = x - 3; - float num = (((0.009508047f * xs) + 0.018557330f)*xs + -0.002224265f)*xs + -0.035035378f; - float denom = (((0.220091105f * xs) + 0.762059164f)*xs + 1.365334981f)*xs + 1.0f; - float R = num / denom; - result = Y * x + R * x; - } - } - - return result; + float t = 1.0f / (1.0f + 0.47047f*x); + return s * (1.0f - + t*(0.3480242f + t*(-0.0958798f + t*0.7478556f)) * expf(-x*x)); } -ccl_device float approx_erfinvf(float z) +ccl_device_inline float approx_erfinvf(float x) { - float p, q, s; - - if(z < 0) { - p = -z; - q = 1 - p; - s = -1; - } - else { - p = z; - q = 1 - z; - s = 1; - } - - return s * approx_erfinvf_impl(p, q); + float ln1_x2 = logf(1.0f - x*x); + float term = 4.546884979448f + ln1_x2 * 0.5f; + return copysignf(1.0f, x) * + sqrtf(sqrtf(term*term - ln1_x2 * 7.142230224076f) - term); } /* Beckmann and GGX microfacet importance sampling from: diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h index dd6abe32fec..59e811fa97e 100644 --- a/intern/cycles/kernel/geom/geom_bvh.h +++ b/intern/cycles/kernel/geom/geom_bvh.h @@ -123,6 +123,36 @@ CCL_NAMESPACE_BEGIN #include "geom_bvh_shadow.h" #endif +#if defined(__VOLUME__) +#define BVH_FUNCTION_NAME bvh_intersect_volume +#define BVH_FUNCTION_FEATURES 0 +#include "geom_bvh_volume.h" +#endif + +#if defined(__VOLUME__) && defined(__INSTANCING__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_instancing +#define BVH_FUNCTION_FEATURES BVH_INSTANCING +#include "geom_bvh_volume.h" +#endif + +#if defined(__VOLUME__) && defined(__HAIR__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_hair +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH +#include "geom_bvh_volume.h" +#endif + +#if defined(__VOLUME__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION +#include "geom_bvh_volume.h" +#endif + +#if defined(__VOLUME__) && defined(__HAIR__) && defined(__OBJECT_MOTION__) +#define BVH_FUNCTION_NAME bvh_intersect_volume_hair_motion +#define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION +#include "geom_bvh_volume.h" +#endif + /* to work around titan bug when using arrays instead of textures */ #if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__) ccl_device_inline @@ -311,5 +341,50 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng) #endif } +/* to work around titan bug when using arrays instead of textures */ +#if !defined(__KERNEL_CUDA__) || defined(__KERNEL_CUDA_TEX_STORAGE__) +ccl_device_inline +#else +ccl_device_noinline +#endif +bool scene_intersect_volume(KernelGlobals *kg, + const Ray *ray, + Intersection *isect) +{ +#ifdef __OBJECT_MOTION__ + if(kernel_data.bvh.have_motion) { +#ifdef __HAIR__ + if(kernel_data.bvh.have_curves) + return bvh_intersect_volume_hair_motion(kg, ray, isect); +#endif /* __HAIR__ */ + + return bvh_intersect_volume_motion(kg, ray, isect); + } +#endif /* __OBJECT_MOTION__ */ + +#ifdef __HAIR__ + if(kernel_data.bvh.have_curves) + return bvh_intersect_volume_hair(kg, ray, isect); +#endif /* __HAIR__ */ + +#ifdef __KERNEL_CPU__ + +#ifdef __INSTANCING__ + if(kernel_data.bvh.have_instancing) + return bvh_intersect_volume_instancing(kg, ray, isect); +#endif /* __INSTANCING__ */ + + return bvh_intersect_volume(kg, ray, isect); +#else /* __KERNEL_CPU__ */ + +#ifdef __INSTANCING__ + return bvh_intersect_volume_instancing(kg, ray, isect); +#else + return bvh_intersect_volume(kg, ray, isect); +#endif /* __INSTANCING__ */ + +#endif /* __KERNEL_CPU__ */ +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h new file mode 100644 index 00000000000..aac0a18647a --- /dev/null +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -0,0 +1,322 @@ +/* + * Adapted from code Copyright 2009-2010 NVIDIA Corporation, + * and code copyright 2009-2012 Intel Corporation + * + * Modifications 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. + */ + +/* This is a template BVH traversal function for volumes, where + * various features can be enabled/disabled. This way we can compile optimized + * versions for each case without new features slowing things down. + * + * BVH_INSTANCING: object instancing + * BVH_HAIR: hair curve rendering + * BVH_MOTION: motion blur rendering + * + */ + +#define FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0) + +ccl_device bool BVH_FUNCTION_NAME(KernelGlobals *kg, + const Ray *ray, + Intersection *isect) +{ + /* todo: + * - test if pushing distance on the stack helps (for non shadow rays) + * - separate version for shadow rays + * - likely and unlikely for if() statements + * - test restrict attribute for pointers + */ + + /* traversal stack in CUDA thread-local memory */ + int traversalStack[BVH_STACK_SIZE]; + traversalStack[0] = ENTRYPOINT_SENTINEL; + + /* traversal variables in registers */ + int stackPtr = 0; + int nodeAddr = kernel_data.bvh.root; + + /* ray parameters in registers */ + float3 P = ray->P; + float3 dir = bvh_clamp_direction(ray->D); + float3 idir = bvh_inverse_direction(dir); + int object = OBJECT_NONE; + + const uint visibility = PATH_RAY_ALL_VISIBILITY; + +#if FEATURE(BVH_MOTION) + Transform ob_tfm; +#endif + + isect->t = ray->t; + isect->object = OBJECT_NONE; + isect->prim = PRIM_NONE; + isect->u = 0.0f; + isect->v = 0.0f; + +#if defined(__KERNEL_SSE2__) + const shuffle_swap_t shuf_identity = shuffle_swap_identity(); + const shuffle_swap_t shuf_swap = shuffle_swap_swap(); + + const ssef pn = cast(ssei(0, 0, 0x80000000, 0x80000000)); + ssef Psplat[3], idirsplat[3]; + shuffle_swap_t shufflexyz[3]; + + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + ssef tsplat(0.0f, 0.0f, -isect->t, -isect->t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + /* traversal loop */ + do { + do { + /* traverse internal nodes */ + while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) { + bool traverseChild0, traverseChild1; + int nodeAddrChild1; + +#if !defined(__KERNEL_SSE2__) + /* Intersect two child bounding boxes, non-SSE version */ + float t = isect->t; + + /* fetch node data */ + float4 node0 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+0); + float4 node1 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+1); + float4 node2 = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+2); + float4 cnodes = kernel_tex_fetch(__bvh_nodes, nodeAddr*BVH_NODE_SIZE+3); + + /* intersect ray against child nodes */ + NO_EXTENDED_PRECISION float c0lox = (node0.x - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0hix = (node0.z - P.x) * idir.x; + NO_EXTENDED_PRECISION float c0loy = (node1.x - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0hiy = (node1.z - P.y) * idir.y; + NO_EXTENDED_PRECISION float c0loz = (node2.x - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0hiz = (node2.z - P.z) * idir.z; + NO_EXTENDED_PRECISION float c0min = max4(min(c0lox, c0hix), min(c0loy, c0hiy), min(c0loz, c0hiz), 0.0f); + NO_EXTENDED_PRECISION float c0max = min4(max(c0lox, c0hix), max(c0loy, c0hiy), max(c0loz, c0hiz), t); + + NO_EXTENDED_PRECISION float c1lox = (node0.y - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1hix = (node0.w - P.x) * idir.x; + NO_EXTENDED_PRECISION float c1loy = (node1.y - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1hiy = (node1.w - P.y) * idir.y; + NO_EXTENDED_PRECISION float c1loz = (node2.y - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1hiz = (node2.w - P.z) * idir.z; + NO_EXTENDED_PRECISION float c1min = max4(min(c1lox, c1hix), min(c1loy, c1hiy), min(c1loz, c1hiz), 0.0f); + NO_EXTENDED_PRECISION float c1max = min4(max(c1lox, c1hix), max(c1loy, c1hiy), max(c1loz, c1hiz), t); + + /* decide which nodes to traverse next */ +#ifdef __VISIBILITY_FLAG__ + /* this visibility test gives a 5% performance hit, how to solve? */ + traverseChild0 = (c0max >= c0min) && (__float_as_uint(cnodes.z) & visibility); + traverseChild1 = (c1max >= c1min) && (__float_as_uint(cnodes.w) & visibility); +#else + traverseChild0 = (c0max >= c0min); + traverseChild1 = (c1max >= c1min); +#endif + +#else // __KERNEL_SSE2__ + /* Intersect two child bounding boxes, SSE3 version adapted from Embree */ + + /* fetch node data */ + const ssef *bvh_nodes = (ssef*)kg->__bvh_nodes.data + nodeAddr*BVH_NODE_SIZE; + const float4 cnodes = ((float4*)bvh_nodes)[3]; + + /* intersect ray against child nodes */ + const ssef tminmaxx = (shuffle_swap(bvh_nodes[0], shufflexyz[0]) - Psplat[0]) * idirsplat[0]; + const ssef tminmaxy = (shuffle_swap(bvh_nodes[1], shufflexyz[1]) - Psplat[1]) * idirsplat[1]; + const ssef tminmaxz = (shuffle_swap(bvh_nodes[2], shufflexyz[2]) - Psplat[2]) * idirsplat[2]; + + /* calculate { c0min, c1min, -c0max, -c1max} */ + ssef minmax = max(max(tminmaxx, tminmaxy), max(tminmaxz, tsplat)); + const ssef tminmax = minmax ^ pn; + + const sseb lrhit = tminmax <= shuffle<2, 3, 0, 1>(tminmax); + + /* decide which nodes to traverse next */ +#ifdef __VISIBILITY_FLAG__ + /* this visibility test gives a 5% performance hit, how to solve? */ + traverseChild0 = (movemask(lrhit) & 1) && (__float_as_uint(cnodes.z) & visibility); + traverseChild1 = (movemask(lrhit) & 2) && (__float_as_uint(cnodes.w) & visibility); +#else + traverseChild0 = (movemask(lrhit) & 1); + traverseChild1 = (movemask(lrhit) & 2); +#endif +#endif // __KERNEL_SSE2__ + + nodeAddr = __float_as_int(cnodes.x); + nodeAddrChild1 = __float_as_int(cnodes.y); + + if(traverseChild0 && traverseChild1) { + /* both children were intersected, push the farther one */ +#if !defined(__KERNEL_SSE2__) + bool closestChild1 = (c1min < c0min); +#else + bool closestChild1 = tminmax[1] < tminmax[0]; +#endif + + if(closestChild1) { + int tmp = nodeAddr; + nodeAddr = nodeAddrChild1; + nodeAddrChild1 = tmp; + } + + ++stackPtr; + traversalStack[stackPtr] = nodeAddrChild1; + } + else { + /* one child was intersected */ + if(traverseChild1) { + nodeAddr = nodeAddrChild1; + } + else if(!traverseChild0) { + /* neither child was intersected */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } + } + + /* if node is leaf, fetch triangle list */ + if(nodeAddr < 0) { + float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1)); + int primAddr = __float_as_int(leaf.x); + +#if FEATURE(BVH_INSTANCING) + if(primAddr >= 0) { +#endif + int primAddr2 = __float_as_int(leaf.y); + + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + + /* primitive intersection */ + for(; primAddr < primAddr2; primAddr++) { + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + + /* intersect ray against primitive */ + uint type = kernel_tex_fetch(__prim_type, primAddr); + + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + triangle_intersect(kg, isect, P, dir, visibility, object, primAddr); + break; + } +#if FEATURE(BVH_MOTION) + case PRIMITIVE_MOTION_TRIANGLE: { + motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); + break; + } +#endif +#if FEATURE(BVH_HAIR) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + else + bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); + break; + } +#endif + default: { + break; + } + } + } + } +#if FEATURE(BVH_INSTANCING) + else { + /* instance push */ + object = kernel_tex_fetch(__prim_object, -primAddr-1); + int object_flag = kernel_tex_fetch(__object_flag, object); + + if(object_flag & SD_OBJECT_HAS_VOLUME) { + +#if FEATURE(BVH_MOTION) + bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); +#else + bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t); +#endif + +#if defined(__KERNEL_SSE2__) + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + ++stackPtr; + traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; + + nodeAddr = kernel_tex_fetch(__object_node, object); + } + else { + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } + } +#endif + } while(nodeAddr != ENTRYPOINT_SENTINEL); + +#if FEATURE(BVH_INSTANCING) + if(stackPtr >= 0) { + kernel_assert(object != OBJECT_NONE); + + /* instance pop */ +#if FEATURE(BVH_MOTION) + bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_tfm); +#else + bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t); +#endif + +#if defined(__KERNEL_SSE2__) + Psplat[0] = ssef(P.x); + Psplat[1] = ssef(P.y); + Psplat[2] = ssef(P.z); + + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); + + gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz); +#endif + + object = OBJECT_NONE; + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } +#endif + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + return (isect->prim != PRIM_NONE); +} + +#undef FEATURE +#undef BVH_FUNCTION_NAME +#undef BVH_FUNCTION_FEATURES + diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 29077a8886c..e68a8370012 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -411,6 +411,8 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false); #ifdef __VOLUME__ Ray volume_ray = *ray; + bool need_update_volume_stack = kernel_data.integrator.use_volumes && + sd->flag & SD_OBJECT_INTERSECTS_VOLUME; #endif /* compute lighting with the BSDF closure */ @@ -430,7 +432,7 @@ ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd #endif #ifdef __VOLUME__ - if(kernel_data.integrator.use_volumes) { + if(need_update_volume_stack) { /* Setup ray from previous surface point to the new one. */ volume_ray.D = normalize_len(hit_ray.P - volume_ray.P, &volume_ray.t); @@ -802,6 +804,8 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, int num_hits = subsurface_scatter_multi_step(kg, sd, bssrdf_sd, state->flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true); #ifdef __VOLUME__ Ray volume_ray = *ray; + bool need_update_volume_stack = kernel_data.integrator.use_volumes && + sd->flag & SD_OBJECT_INTERSECTS_VOLUME; #endif /* compute lighting with the BSDF closure */ @@ -811,7 +815,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg, path_state_branch(&hit_state, j, num_samples); #ifdef __VOLUME__ - if(kernel_data.integrator.use_volumes) { + if(need_update_volume_stack) { /* Setup ray from previous surface point to the new one. */ float3 P = ray_offset(bssrdf_sd[hit].P, -bssrdf_sd[hit].Ng); volume_ray.D = normalize_len(P - volume_ray.P, diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 7c95f8cf14a..2fe1cd87072 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -615,8 +615,12 @@ enum ShaderDataFlag { SD_OBJECT_MOTION = 1048576, /* has object motion blur */ SD_TRANSFORM_APPLIED = 2097152, /* vertices have transform applied */ SD_NEGATIVE_SCALE_APPLIED = 4194304, /* vertices have negative scale applied */ + SD_OBJECT_HAS_VOLUME = 8388608, /* object has a volume shader */ + SD_OBJECT_INTERSECTS_VOLUME = 16777216, /* object intersects AABB of an object with volume shader */ - SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED|SD_NEGATIVE_SCALE_APPLIED) + SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED| + SD_NEGATIVE_SCALE_APPLIED|SD_OBJECT_HAS_VOLUME| + SD_OBJECT_INTERSECTS_VOLUME) }; struct KernelGlobals; diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index 794ce925777..dd947a54530 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -985,9 +985,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg, enclosed_index < VOLUME_STACK_SIZE - 1) { Intersection isect; - if(!scene_intersect(kg, &volume_ray, PATH_RAY_ALL_VISIBILITY, - &isect, NULL, 0.0f, 0.0f)) - { + if(!scene_intersect_volume(kg, &volume_ray, &isect)) { break; } diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 28b6c994568..110adb4d036 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -276,17 +276,15 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) /* Camera in volume. */ kcam->is_inside_volume = 0; - if(use_camera_in_volume) { - BoundBox viewplane_boundbox = viewplane_bounds_get(); - for(size_t i = 0; i < scene->objects.size(); ++i) { - Object *object = scene->objects[i]; - if(object->mesh->has_volume && - viewplane_boundbox.intersects(object->bounds)) - { - /* TODO(sergey): Consider adding more grained check. */ - kcam->is_inside_volume = 1; - break; - } + BoundBox viewplane_boundbox = viewplane_bounds_get(); + for(size_t i = 0; i < scene->objects.size(); ++i) { + Object *object = scene->objects[i]; + if(object->mesh->has_volume && + viewplane_boundbox.intersects(object->bounds)) + { + /* TODO(sergey): Consider adding more grained check. */ + kcam->is_inside_volume = 1; + break; } } } diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 3054137309d..788ae7b9bb6 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -102,13 +102,6 @@ public: bool need_device_update; int previous_need_motion; - /* Camera in volume. */ - /* TODO(sergey): Get rid of this argument once - * cameras in volume considered fast enough for - * the regular kernel. - */ - bool use_camera_in_volume; - /* functions */ Camera(); ~Camera(); diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 076cc3d8b63..eb2c3333c44 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -176,6 +176,10 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani img->frame = frame; img->need_load = true; } + if(img->use_alpha != use_alpha) { + img->use_alpha = use_alpha; + img->need_load = true; + } img->users++; return slot; } @@ -219,6 +223,10 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani img->frame = frame; img->need_load = true; } + if(img->use_alpha != use_alpha) { + img->use_alpha = use_alpha; + img->need_load = true; + } img->users++; return slot+tex_image_byte_start; } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 54cfab42a97..42103396b53 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -1032,7 +1032,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen if(!need_update) return; - /* update normals */ + /* update normals and flags */ foreach(Mesh *mesh, scene->meshes) { mesh->has_volume = false; foreach(uint shader, mesh->used_shaders) { @@ -1109,6 +1109,8 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen bool motion_blur = false; #endif + /* update obejcts */ + vector<Object *> volume_objects; foreach(Object *object, scene->objects) object->compute_bounds(motion_blur); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 1f148d34ea6..46ddab235d9 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -75,8 +75,14 @@ void Object::compute_bounds(bool motion_blur) bounds.grow(mbounds.transformed(&ttfm)); } } - else - bounds = mbounds.transformed(&tfm); + else { + if(mesh->transform_applied) { + bounds = mbounds; + } + else { + bounds = mbounds.transformed(&tfm); + } + } } void Object::apply_transform(bool apply_to_motion) @@ -372,8 +378,6 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc device_free(device, dscene); - need_update = false; - if(scene->objects.size() == 0) return; @@ -392,6 +396,46 @@ void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *sc progress.set_status("Updating Objects", "Applying Static Transformations"); apply_static_transforms(dscene, scene, object_flag, progress); } +} + +void ObjectManager::device_update_flags(Device *device, DeviceScene *dscene, + Scene *scene, Progress& progress) +{ + if(!need_update) + return; + + need_update = false; + + if(scene->objects.size() == 0) + return; + + /* object info flag */ + uint *object_flag = dscene->object_flag.get_data(); + + vector<Object *> volume_objects; + foreach(Object *object, scene->objects) { + if(object->mesh->has_volume) { + volume_objects.push_back(object); + } + } + + int object_index = 0; + foreach(Object *object, scene->objects) { + if(object->mesh->has_volume) { + object_flag[object_index] |= SD_OBJECT_HAS_VOLUME; + } + + foreach(Object *volume_object, volume_objects) { + if(object == volume_object) { + continue; + } + if(object->bounds.intersects(volume_object->bounds)) { + object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME; + break; + } + } + ++object_index; + } /* allocate object flag */ device->tex_alloc("__object_flag", dscene->object_flag); diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 677526b715f..2c69b83a2e9 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -76,6 +76,7 @@ public: void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress); + void device_update_flags(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index d0de8c51300..6c3f98bc9b0 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -175,6 +175,11 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; + progress.set_status("Updating Objects Flags"); + object_manager->device_update_flags(device, &dscene, this, progress); + + if(progress.get_cancel()) return; + progress.set_status("Updating Hair Systems"); curve_system_manager->device_update(device, &dscene, this, progress); diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 1969572530d..ffd4299bc39 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -844,14 +844,15 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): self.prop_unified_size(row, context, brush, "use_pressure_size") # strength, use_strength_pressure, and use_strength_attenuation - if capabilities.has_strength: - col.separator() - row = col.row(align=True) + col.separator() + row = col.row(align=True) + + if capabilities.has_space_attenuation: + row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True) - if capabilities.has_space_attenuation: - row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True) + self.prop_unified_strength(row, context, brush, "strength", text="Strength") - self.prop_unified_strength(row, context, brush, "strength", text="Strength") + if capabilities.has_strength_pressure: self.prop_unified_strength(row, context, brush, "use_pressure_strength") # auto_smooth_factor and use_inverse_smooth_pressure diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 661fe03912f..105c83f9864 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 272 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 399bea1b610..cad062ac63d 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -3014,10 +3014,17 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int if (UNLIKELY(c == 0)) { continue; } + else if (UNLIKELY(c < 3)) { + STACK_DISCARD(oldl, c); + STACK_DISCARD(mloop, c); + continue; + } + mp_new = STACK_PUSH_RET_PTR(mpoly); *mp_new = *mp; mp_new->totloop = c; + BLI_assert(mp_new->totloop >= 3); mp_new->loopstart = STACK_SIZE(mloop) - c; STACK_PUSH(oldp, i); diff --git a/source/blender/blenlib/BLI_stackdefines.h b/source/blender/blenlib/BLI_stackdefines.h index da9bf5ea04c..864a7704aa9 100644 --- a/source/blender/blenlib/BLI_stackdefines.h +++ b/source/blender/blenlib/BLI_stackdefines.h @@ -64,6 +64,13 @@ stack[_i] = stack[_##stack##_index]; \ } \ } (void)0 +#define STACK_DISCARD(stack, n) \ + { \ + const unsigned int _n = n; \ + BLI_assert(_##stack##_index >= _n); \ + (void)stack; \ + _##stack##_index -= _n; \ + } (void)0 #ifdef __GNUC__ #define STACK_SWAP(stack_a, stack_b) { \ SWAP(typeof(stack_a), stack_a, stack_b); \ diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 22868035a13..d8da0a12b50 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -390,6 +390,14 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 272, 1)) { + Brush *br; + for (br = main->brush.first; br; br = br->id.next) { + if ((br->ob_mode & OB_MODE_SCULPT) && ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK)) + br->alpha = 1.0f; + } + } if (!DNA_struct_elem_find(fd->filesdna, "Image", "float", "gen_color")) { Image *image; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 9c8c3c29b9c..e024f837feb 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -809,10 +809,10 @@ static float brush_strength(Sculpt *sd, StrokeCache *cache, float feather, Unifi return alpha * pressure * feather; case SCULPT_TOOL_SNAKE_HOOK: - return feather; + return root_alpha * feather; case SCULPT_TOOL_GRAB: - return feather; + return root_alpha * feather; case SCULPT_TOOL_ROTATE: return alpha * pressure * feather; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 1ff99271146..bbc2e0572fa 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -264,7 +264,7 @@ static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr) return (!(br->flag & BRUSH_ANCHORED)); } -static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_strength_pressure_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK); @@ -689,7 +689,7 @@ static void rna_def_sculpt_capabilities(BlenderRNA *brna) SCULPT_TOOL_CAPABILITY(has_secondary_color, "Has Secondary Color"); SCULPT_TOOL_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke"); SCULPT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation"); - SCULPT_TOOL_CAPABILITY(has_strength, "Has Strength"); + SCULPT_TOOL_CAPABILITY(has_strength_pressure, "Has Strength Pressure"); SCULPT_TOOL_CAPABILITY(has_gravity, "Has Gravity"); #undef SCULPT_CAPABILITY diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 66796480542..bae75d8693f 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -406,6 +406,9 @@ static DerivedMesh *arrayModifier_doArray( const bool use_merge = amd->flags & MOD_ARR_MERGE; const bool use_recalc_normals = (dm->dirty & DM_DIRTY_NORMALS) || use_merge; + const bool use_offset_ob = ((amd->offset_type & MOD_ARR_OFF_OBJ) && amd->offset_ob); + /* allow pole vertices to be used by many faces */ + const bool with_follow = use_offset_ob; int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0; int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0; @@ -454,7 +457,7 @@ static DerivedMesh *arrayModifier_doArray( offset[3][j] += amd->scale[j] * vertarray_size(src_mvert, chunk_nverts, j); } - if ((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) { + if (use_offset_ob) { float obinv[4][4]; float result_mat[4][4]; @@ -606,10 +609,12 @@ static DerivedMesh *arrayModifier_doArray( int target = full_doubles_map[prev_chunk_index]; if (target != -1) { target += chunk_nverts; /* translate mapping */ - /* The rule here is to not follow mapping to chunk N-2, which could be too far - * so if target vertex was itself mapped, then this vertex is not mapped */ - if (full_doubles_map[target] != -1) { - target = -1; + if (!with_follow) { + /* The rule here is to not follow mapping to chunk N-2, which could be too far + * so if target vertex was itself mapped, then this vertex is not mapped */ + if (full_doubles_map[target] != -1) { + target = -1; + } } } full_doubles_map[this_chunk_index] = target; @@ -624,7 +629,7 @@ static DerivedMesh *arrayModifier_doArray( c * chunk_nverts, chunk_nverts, amd->merge_dist, - false); + with_follow); } } } @@ -644,7 +649,7 @@ static DerivedMesh *arrayModifier_doArray( first_chunk_start, first_chunk_nverts, amd->merge_dist, - false); + with_follow); } /* start capping */ @@ -711,7 +716,12 @@ static DerivedMesh *arrayModifier_doArray( if (use_merge) { for (i = 0; i < result_nverts; i++) { if (full_doubles_map[i] != -1) { - tot_doubles++; + if (i == full_doubles_map[i]) { + full_doubles_map[i] = -1; + } + else { + tot_doubles++; + } } } if (tot_doubles > 0) { diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 76986583ef5..7349ca9f9ef 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -60,7 +60,7 @@ static void copyData(ModifierData *md, ModifierData *target) static bool isDisabled(ModifierData *UNUSED(md), int UNUSED(useRenderParams)) { - return 0; + return false; } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) @@ -75,6 +75,11 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) } +static bool dependsOnNormals(ModifierData *UNUSED(md)) +{ + return true; +} + static DerivedMesh *WireframeModifier_do( WireframeModifierData *wmd, Object *ob, DerivedMesh *dm) { DerivedMesh *result; @@ -135,7 +140,7 @@ ModifierTypeInfo modifierType_Wireframe = { /* isDisabled */ isDisabled, /* updateDepgraph */ NULL, /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, + /* dependsOnNormals */ dependsOnNormals, /* foreachObjectLink */ NULL, /* foreachIDLink */ NULL, /* foreachTexLink */ NULL, |