Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2017-03-28 11:41:10 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2017-03-28 11:41:10 +0300
commit885260117d6a9080ce073a1fb402b7af060f8645 (patch)
tree1769a4c180115a0fdda86d5554159c43691f461b /intern
parent6d21970aa06a31398ed4a78b1c596f30a0b9ee87 (diff)
parente1909958d9ec48333a7bfd0d34aede66efc9b1ad (diff)
Merge branch 'master' into blender2.8
Conflicts: source/blender/blenloader/intern/readfile.c source/blender/windowmanager/intern/wm_window.c
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/addon/properties.py6
-rw-r--r--intern/cycles/blender/addon/ui.py4
-rw-r--r--intern/cycles/blender/blender_object.cpp7
-rw-r--r--intern/cycles/blender/blender_shader.cpp16
-rw-r--r--intern/cycles/device/device.cpp6
-rw-r--r--intern/cycles/device/device.h10
-rw-r--r--intern/cycles/kernel/bvh/bvh.h51
-rw-r--r--intern/cycles/kernel/bvh/bvh_shadow_all.h14
-rw-r--r--intern/cycles/kernel/bvh/qbvh_shadow_all.h11
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h124
-rw-r--r--intern/cycles/kernel/kernel_emission.h7
-rw-r--r--intern/cycles/kernel/kernel_path.h48
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h44
-rw-r--r--intern/cycles/kernel/kernel_path_common.h2
-rw-r--r--intern/cycles/kernel/kernel_path_state.h6
-rw-r--r--intern/cycles/kernel/kernel_path_subsurface.h4
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h61
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h22
-rw-r--r--intern/cycles/kernel/kernel_random.h37
-rw-r--r--intern/cycles/kernel/kernel_shader.h13
-rw-r--r--intern/cycles/kernel/kernel_shadow.h65
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h2
-rw-r--r--intern/cycles/kernel/kernel_types.h32
-rw-r--r--intern/cycles/kernel/kernel_volume.h6
-rw-r--r--intern/cycles/kernel/split/kernel_buffer_update.h22
-rw-r--r--intern/cycles/kernel/split/kernel_direct_lighting.h36
-rw-r--r--intern/cycles/kernel/split/kernel_do_volume.h9
-rw-r--r--intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h26
-rw-r--r--intern/cycles/kernel/split/kernel_indirect_background.h2
-rw-r--r--intern/cycles/kernel/split/kernel_next_iteration_setup.h13
-rw-r--r--intern/cycles/kernel/split/kernel_path_init.h7
-rw-r--r--intern/cycles/kernel/split/kernel_scene_intersect.h2
-rw-r--r--intern/cycles/kernel/split/kernel_shader_eval.h7
-rw-r--r--intern/cycles/kernel/split/kernel_subsurface_scatter.h5
-rw-r--r--intern/cycles/kernel/svm/svm_voxel.h2
-rw-r--r--intern/cycles/render/graph.cpp25
-rw-r--r--intern/cycles/render/graph.h3
-rw-r--r--intern/cycles/render/object.cpp8
-rw-r--r--intern/cycles/render/object.h1
-rw-r--r--intern/cycles/render/osl.cpp2
-rw-r--r--intern/cycles/render/session.cpp3
-rw-r--r--intern/cycles/render/svm.cpp2
-rw-r--r--intern/cycles/util/util_math.h2
-rw-r--r--intern/ghost/GHOST_C-api.h5
-rw-r--r--intern/ghost/GHOST_IWindow.h6
-rw-r--r--intern/ghost/GHOST_Types.h1
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp78
-rw-r--r--intern/ghost/intern/GHOST_Window.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp16
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp18
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h11
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp45
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h2
55 files changed, 826 insertions, 148 deletions
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 6c5bcf09305..cbf469b3a89 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -1096,6 +1096,12 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
default=1.0,
)
+ cls.is_shadow_catcher = BoolProperty(
+ name="Shadow Catcher",
+ description="Only render shadows on this object, for compositing renders into real footage",
+ default=False,
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Object.cycles
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index eec897474c5..4894b301606 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -268,7 +268,7 @@ class CyclesRender_PT_geometry(CyclesButtonsPanel, Panel):
row = col.row()
row.prop(ccscene, "minimum_width", text="Min Pixels")
- row.prop(ccscene, "maximum_width", text="Max Ext.")
+ row.prop(ccscene, "maximum_width", text="Max Extension")
class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
@@ -786,6 +786,8 @@ class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
if ob.type != 'LAMP':
flow.prop(visibility, "shadow")
+ layout.prop(cob, "is_shadow_catcher")
+
col = layout.column()
col.label(text="Performance:")
row = col.row()
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 637cf7abda8..968861391a2 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -343,6 +343,13 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
object_updated = true;
}
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher");
+ if(is_shadow_catcher != object->is_shadow_catcher) {
+ object->is_shadow_catcher = is_shadow_catcher;
+ object_updated = true;
+ }
+
/* object sync
* transform comparison should not be needed, but duplis don't work perfect
* in the depsgraph and may not signal changes, so this is a workaround */
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 8baa53fc2ec..f35565d8330 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -28,6 +28,7 @@
#include "util_debug.h"
#include "util_string.h"
+#include "util_task.h"
CCL_NAMESPACE_BEGIN
@@ -1164,6 +1165,8 @@ void BlenderSync::sync_materials(bool update_all)
/* material loop */
BL::BlendData::materials_iterator b_mat;
+ TaskPool pool;
+
for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
Shader *shader;
@@ -1199,9 +1202,22 @@ void BlenderSync::sync_materials(bool update_all)
shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP;
shader->set_graph(graph);
+
+ /* By simplifying the shader graph as soon as possible, some redundant shader nodes
+ * might be removed which prevents loading unneccessary attributes later.
+ *
+ * However, since graph simplification also accounts for e.g. mix weight, this would
+ * cause frequent expensive resyncs in interactive sessions, so for those sessions
+ * optimization is only performed right before compiling. */
+ if(!preview) {
+ pool.push(function_bind(&ShaderGraph::simplify, shader->graph, scene));
+ }
+
shader->tag_update(scene);
}
}
+
+ pool.wait_work();
}
/* Sync World */
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 6b07b9d04bd..21eb3379694 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -48,11 +48,11 @@ std::ostream& operator <<(std::ostream &os,
os << "Max nodes group: " << requested_features.max_nodes_group << std::endl;
/* TODO(sergey): Decode bitflag into list of names. */
os << "Nodes features: " << requested_features.nodes_features << std::endl;
- os << "Use hair: "
+ os << "Use Hair: "
<< string_from_bool(requested_features.use_hair) << std::endl;
- os << "Use object motion: "
+ os << "Use Object Motion: "
<< string_from_bool(requested_features.use_object_motion) << std::endl;
- os << "Use camera motion: "
+ os << "Use Camera Motion: "
<< string_from_bool(requested_features.use_camera_motion) << std::endl;
os << "Use Baking: "
<< string_from_bool(requested_features.use_baking) << std::endl;
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index ec15a254f81..468a5b1515a 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -121,6 +121,9 @@ public:
/* Use Transparent shadows */
bool use_transparent;
+ /* Use various shadow tricks, such as shadow catcher. */
+ bool use_shadow_tricks;
+
DeviceRequestedFeatures()
{
/* TODO(sergey): Find more meaningful defaults. */
@@ -137,6 +140,7 @@ public:
use_integrator_branched = false;
use_patch_evaluation = false;
use_transparent = false;
+ use_shadow_tricks = false;
}
bool modified(const DeviceRequestedFeatures& requested_features)
@@ -153,7 +157,8 @@ public:
use_volume == requested_features.use_volume &&
use_integrator_branched == requested_features.use_integrator_branched &&
use_patch_evaluation == requested_features.use_patch_evaluation &&
- use_transparent == requested_features.use_transparent);
+ use_transparent == requested_features.use_transparent &&
+ use_shadow_tricks == requested_features.use_shadow_tricks);
}
/* Convert the requested features structure to a build options,
@@ -197,6 +202,9 @@ public:
if(!use_transparent && !use_volume) {
build_options += " -D__NO_TRANSPARENT__";
}
+ if(!use_shadow_tricks) {
+ build_options += " -D__NO_SHADOW_TRICKS__";
+ }
return build_options;
}
};
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index 598e138dbea..1358288f832 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -230,30 +230,63 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
#endif
#ifdef __SHADOW_RECORD_ALL__
-ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits)
+ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ int skip_object,
+ uint max_hits,
+ uint *num_hits)
{
# ifdef __OBJECT_MOTION__
if(kernel_data.bvh.have_motion) {
# ifdef __HAIR__
- if(kernel_data.bvh.have_curves)
- return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, max_hits, num_hits);
+ if(kernel_data.bvh.have_curves) {
+ return bvh_intersect_shadow_all_hair_motion(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
+ }
# endif /* __HAIR__ */
- return bvh_intersect_shadow_all_motion(kg, ray, isect, max_hits, num_hits);
+ return bvh_intersect_shadow_all_motion(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
}
# endif /* __OBJECT_MOTION__ */
# ifdef __HAIR__
- if(kernel_data.bvh.have_curves)
- return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits);
+ if(kernel_data.bvh.have_curves) {
+ return bvh_intersect_shadow_all_hair(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
+ }
# endif /* __HAIR__ */
# ifdef __INSTANCING__
- if(kernel_data.bvh.have_instancing)
- return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits);
+ if(kernel_data.bvh.have_instancing) {
+ return bvh_intersect_shadow_all_instancing(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
+ }
# endif /* __INSTANCING__ */
- return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits);
+ return bvh_intersect_shadow_all(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
}
#endif /* __SHADOW_RECORD_ALL__ */
diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h
index 8f7c005e961..b2555b3a6bb 100644
--- a/intern/cycles/kernel/bvh/bvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h
@@ -45,6 +45,7 @@ ccl_device_inline
bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
+ const int skip_object,
const uint max_hits,
uint *num_hits)
{
@@ -189,6 +190,16 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
while(prim_addr < prim_addr2) {
kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
+#ifdef __SHADOW_TRICKS__
+ uint tri_object = (object == OBJECT_NONE)
+ ? kernel_tex_fetch(__prim_object, prim_addr)
+ : object;
+ if(tri_object == skip_object) {
+ ++prim_addr;
+ continue;
+ }
+#endif
+
bool hit;
/* todo: specialized intersect functions which don't fill in
@@ -398,6 +409,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
+ const int skip_object,
const uint max_hits,
uint *num_hits)
{
@@ -406,6 +418,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
ray,
isect_array,
+ skip_object,
max_hits,
num_hits);
}
@@ -416,6 +429,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
return BVH_FUNCTION_FULL_NAME(BVH)(kg,
ray,
isect_array,
+ skip_object,
max_hits,
num_hits);
}
diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
index 5d960787134..1663e23c334 100644
--- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
@@ -33,6 +33,7 @@
ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
+ const int skip_object,
const uint max_hits,
uint *num_hits)
{
@@ -270,6 +271,16 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
while(prim_addr < prim_addr2) {
kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
+#ifdef __SHADOW_TRICKS__
+ uint tri_object = (object == OBJECT_NONE)
+ ? kernel_tex_fetch(__prim_object, prim_addr)
+ : object;
+ if(tri_object == skip_object) {
+ ++prim_addr;
+ continue;
+ }
+#endif
+
bool hit;
/* todo: specialized intersect functions which don't fill in
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index c589c112cc2..823d30dde78 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -52,10 +52,17 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
{
eval->diffuse = value;
}
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis = make_float3(0.0f, 0.0f, 0.0f);
+#endif
}
-ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
+ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value, float mis_weight)
{
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis += value;
+#endif
+ value *= mis_weight;
#ifdef __PASSES__
if(eval->use_light_pass) {
if(CLOSURE_IS_BSDF_DIFFUSE(type))
@@ -96,7 +103,7 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
}
}
-ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
+ccl_device_inline void bsdf_eval_mis(BsdfEval *eval, float value)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
@@ -115,8 +122,19 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
}
}
+ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
+{
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis *= value;
+#endif
+ bsdf_eval_mis(eval, value);
+}
+
ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value)
{
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis *= value;
+#endif
#ifdef __PASSES__
if(eval->use_light_pass) {
eval->diffuse *= value;
@@ -134,7 +152,7 @@ ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value)
#endif
}
-ccl_device_inline float3 bsdf_eval_sum(BsdfEval *eval)
+ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
@@ -198,6 +216,12 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
{
L->emission = make_float3(0.0f, 0.0f, 0.0f);
}
+
+#ifdef __SHADOW_TRICKS__
+ L->path_total = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow_color = make_float3(0.0f, 0.0f, 0.0f);
+#endif
}
ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput,
@@ -252,7 +276,12 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 thro
}
}
-ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 alpha, float3 bsdf, float3 ao, int bounce)
+ccl_device_inline void path_radiance_accum_ao(PathRadiance *L,
+ float3 throughput,
+ float3 alpha,
+ float3 bsdf,
+ float3 ao,
+ int bounce)
{
#ifdef __PASSES__
if(L->use_light_pass) {
@@ -271,6 +300,26 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput
{
L->emission += throughput*bsdf*ao;
}
+
+#ifdef __SHADOW_TRICKS__
+ float3 light = throughput * bsdf;
+ L->path_total += light;
+ L->path_total_shaded += ao * light;
+#endif
+}
+
+ccl_device_inline void path_radiance_accum_total_ao(
+ PathRadiance *L,
+ float3 throughput,
+ float3 bsdf)
+{
+#ifdef __SHADOW_TRICKS__
+ L->path_total += throughput * bsdf;
+#else
+ (void) L;
+ (void) throughput;
+ (void) bsdf;
+#endif
}
ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp)
@@ -301,15 +350,38 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
{
L->emission += throughput*bsdf_eval->diffuse*shadow;
}
+
+#ifdef __SHADOW_TRICKS__
+ float3 light = throughput * bsdf_eval->sum_no_mis;
+ L->path_total += light;
+ L->path_total_shaded += shadow * light;
+#endif
+}
+
+ccl_device_inline void path_radiance_accum_total_light(
+ PathRadiance *L,
+ float3 throughput,
+ const BsdfEval *bsdf_eval)
+{
+#ifdef __SHADOW_TRICKS__
+ L->path_total += throughput * bsdf_eval->sum_no_mis;
+#else
+ (void) L;
+ (void) throughput;
+ (void) bsdf_eval;
+#endif
}
-ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
+ccl_device_inline void path_radiance_accum_background(PathRadiance *L,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float3 value)
{
#ifdef __PASSES__
if(L->use_light_pass) {
- if(bounce == 0)
+ if(state->bounce == 0)
L->background += throughput*value;
- else if(bounce == 1)
+ else if(state->bounce == 1)
L->direct_emission += throughput*value;
else
L->indirect += throughput*value;
@@ -319,6 +391,13 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 th
{
L->emission += throughput*value;
}
+
+#ifdef __SHADOW_TRICKS__
+ L->path_total += throughput * value;
+ if(state->flag & PATH_RAY_SHADOW_CATCHER_ONLY) {
+ L->path_total_shaded += throughput * value;
+ }
+#endif
}
ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
@@ -501,5 +580,34 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
L->emission += L_sample->emission * fac;
}
-CCL_NAMESPACE_END
+#ifdef __SHADOW_TRICKS__
+/* Calculate current shadow of the path. */
+ccl_device_inline float path_radiance_sum_shadow(const PathRadiance *L)
+{
+ float path_total = average(L->path_total);
+ float path_total_shaded = average(L->path_total_shaded);
+ if(path_total != 0.0f) {
+ return path_total_shaded / path_total;
+ }
+ return 1.0f;
+}
+/* Calculate final light sum and transparency for shadow catcher object. */
+ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg,
+ const PathRadiance *L,
+ ccl_addr_space float* L_transparent)
+{
+ const float shadow = path_radiance_sum_shadow(L);
+ float3 L_sum;
+ if(kernel_data.background.transparent) {
+ *L_transparent = shadow;
+ L_sum = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else {
+ L_sum = L->shadow_color * shadow;
+ }
+ return L_sum;
+}
+#endif
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index cf14a159e47..9e7d51f23f5 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -156,7 +156,12 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
if(bsdf_eval_is_zero(eval))
return false;
- if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
+ if(kernel_data.integrator.light_inv_rr_threshold > 0.0f
+#ifdef __SHADOW_TRICKS__
+ && (state->flag & PATH_RAY_SHADOW_CATCHER) == 0
+#endif
+ )
+ {
float probability = max3(fabs(bsdf_eval_sum(eval))) * kernel_data.integrator.light_inv_rr_threshold;
if(probability < 1.0f) {
if(rand_terminate >= probability) {
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index ebf03ad9778..31d5285796c 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -92,6 +92,9 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
path_radiance_accum_ao(L, throughput, ao_alpha, ao_bsdf, ao_shadow, state->bounce);
}
+ else {
+ path_radiance_accum_total_ao(L, throughput, ao_bsdf);
+ }
}
}
@@ -290,9 +293,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* sample background shader */
float3 L_background = indirect_background(kg, emission_sd, state, ray);
path_radiance_accum_background(L,
+ state,
throughput,
- L_background,
- state->bounce);
+ L_background);
#endif /* __BACKGROUND__ */
break;
@@ -312,6 +315,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
shader_merge_closures(sd);
#endif /* __BRANCHED_PATH__ */
+#ifdef __SHADOW_TRICKS__
+ if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
+
/* blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy) */
if(kernel_data.integrator.filter_glossy != FLT_MAX) {
@@ -374,7 +383,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
- uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
float bssrdf_u, bssrdf_v;
path_state_rng_2D(kg,
@@ -396,7 +405,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#if defined(__EMISSION__) && defined(__BRANCHED_PATH__)
if(kernel_data.integrator.use_direct_light) {
- int all = kernel_data.integrator.sample_all_lights_indirect;
+ int all = (kernel_data.integrator.sample_all_lights_indirect) ||
+ (state->flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(kg,
rng,
sd,
@@ -466,7 +476,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
+ lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
}
if(state.bounce > kernel_data.integrator.ao_bounces) {
@@ -611,7 +621,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
#ifdef __BACKGROUND__
/* sample background shader */
float3 L_background = indirect_background(kg, &emission_sd, &state, &ray);
- path_radiance_accum_background(&L, throughput, L_background, state.bounce);
+ path_radiance_accum_background(&L, &state, throughput, L_background);
#endif /* __BACKGROUND__ */
break;
@@ -625,6 +635,21 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF);
shader_eval_surface(kg, &sd, rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+#ifdef __SHADOW_TRICKS__
+ if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ if(state.flag & PATH_RAY_CAMERA) {
+ state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
+ state.catcher_object = sd.object;
+ if(!kernel_data.background.transparent) {
+ L.shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
+ }
+ }
+ }
+ else {
+ state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
+
/* holdout */
#ifdef __HOLDOUT__
if(((sd.flag & SD_HOLDOUT) ||
@@ -742,7 +767,16 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
}
#endif /* __SUBSURFACE__ */
- float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
+ float3 L_sum;
+#ifdef __SHADOW_TRICKS__
+ if(state.flag & PATH_RAY_SHADOW_CATCHER) {
+ L_sum = path_radiance_sum_shadowcatcher(kg, &L, &L_transparent);
+ }
+ else
+#endif /* __SHADOW_TRICKS__ */
+ {
+ L_sum = path_radiance_clamp_and_sum(kg, &L);
+ }
kernel_write_light_passes(kg, buffer, &L, sample);
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index d58960cae4e..36fd6c95fe7 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -55,8 +55,12 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow))
+ if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
path_radiance_accum_ao(L, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow, state->bounce);
+ }
+ else {
+ path_radiance_accum_total_ao(L, throughput*num_samples_inv, ao_bsdf);
+ }
}
}
}
@@ -147,7 +151,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
continue;
/* set up random number generator */
- uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
int num_samples = kernel_data.integrator.subsurface_samples;
float num_samples_inv = 1.0f/num_samples;
RNG bssrdf_rng = cmj_hash(*rng, i);
@@ -206,7 +210,8 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
#ifdef __EMISSION__
/* direct light */
if(kernel_data.integrator.use_direct_light) {
- int all = kernel_data.integrator.sample_all_lights_direct;
+ int all = (kernel_data.integrator.sample_all_lights_direct) ||
+ (state->flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(
kg,
rng,
@@ -280,7 +285,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
+ lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
}
bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
@@ -461,7 +466,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __BACKGROUND__
/* sample background shader */
float3 L_background = indirect_background(kg, &emission_sd, &state, &ray);
- path_radiance_accum_background(&L, throughput, L_background, state.bounce);
+ path_radiance_accum_background(&L, &state, throughput, L_background);
#endif /* __BACKGROUND__ */
break;
@@ -472,6 +477,21 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
shader_merge_closures(&sd);
+#ifdef __SHADOW_TRICKS__
+ if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ if(state.flag & PATH_RAY_CAMERA) {
+ state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
+ state.catcher_object = sd.object;
+ if(!kernel_data.background.transparent) {
+ L.shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
+ }
+ }
+ }
+ else {
+ state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
+
/* holdout */
#ifdef __HOLDOUT__
if((sd.flag & SD_HOLDOUT) || (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) {
@@ -544,7 +564,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __EMISSION__
/* direct light */
if(kernel_data.integrator.use_direct_light) {
- int all = kernel_data.integrator.sample_all_lights_direct;
+ int all = (kernel_data.integrator.sample_all_lights_direct) ||
+ (state.flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(kg, rng,
&sd, &emission_sd, &hit_state, throughput, 1.0f, &L, all);
}
@@ -581,7 +602,16 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#endif /* __VOLUME__ */
}
- float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
+ float3 L_sum;
+#ifdef __SHADOW_TRICKS__
+ if(state.flag & PATH_RAY_SHADOW_CATCHER) {
+ L_sum = path_radiance_sum_shadowcatcher(kg, &L, &L_transparent);
+ }
+ else
+#endif /* __SHADOW_TRICKS__ */
+ {
+ L_sum = path_radiance_clamp_and_sum(kg, &L);
+ }
kernel_write_light_passes(kg, buffer, &L, sample);
diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h
index 7b903556bf9..596210f442e 100644
--- a/intern/cycles/kernel/kernel_path_common.h
+++ b/intern/cycles/kernel/kernel_path_common.h
@@ -22,7 +22,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
ccl_global uint *rng_state,
int sample,
int x, int y,
- ccl_addr_space RNG *rng,
+ RNG *rng,
ccl_addr_space Ray *ray)
{
float filter_u;
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index 661dc52fb31..c0cd2a63120 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -19,7 +19,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void path_state_init(KernelGlobals *kg,
ShaderData *stack_sd,
ccl_addr_space PathState *state,
- ccl_addr_space RNG *rng,
+ RNG *rng,
int sample,
ccl_addr_space Ray *ray)
{
@@ -54,6 +54,10 @@ ccl_device_inline void path_state_init(KernelGlobals *kg,
state->volume_stack[0].shader = SHADER_NONE;
}
#endif
+
+#ifdef __SHADOW_TRICKS__
+ state->catcher_object = OBJECT_NONE;
+#endif
}
ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label)
diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h
index d22ec992074..10b568ac3dd 100644
--- a/intern/cycles/kernel/kernel_path_subsurface.h
+++ b/intern/cycles/kernel/kernel_path_subsurface.h
@@ -28,7 +28,7 @@ bool kernel_path_subsurface_scatter(
ShaderData *emission_sd,
PathRadiance *L,
ccl_addr_space PathState *state,
- ccl_addr_space RNG *rng,
+ RNG *rng,
ccl_addr_space Ray *ray,
ccl_addr_space float3 *throughput,
ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
@@ -47,7 +47,7 @@ bool kernel_path_subsurface_scatter(
*/
kernel_assert(!ss_indirect->tracing);
- uint lcg_state = lcg_state_init_addrspace(rng, state, 0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
SubsurfaceIntersection ss_isect;
float bssrdf_u, bssrdf_v;
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index efa23038089..076c82f3853 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -16,12 +16,18 @@
CCL_NAMESPACE_BEGIN
-#if (defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__)) && !defined(__SPLIT_KERNEL__)
-
+#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__)
/* branched path tracing: connect path directly to position on one or more lights and add it to L */
-ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, ShaderData *emission_sd, PathState *state, float3 throughput,
- float num_samples_adjust, PathRadiance *L, int sample_all_lights)
+ccl_device_noinline void kernel_branched_path_surface_connect_light(
+ KernelGlobals *kg,
+ RNG *rng,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float num_samples_adjust,
+ PathRadiance *L,
+ int sample_all_lights)
{
#ifdef __EMISSION__
/* sample illumination from lights to find path contribution */
@@ -66,6 +72,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
/* accumulate */
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput*num_samples_inv, &L_light);
+ }
}
}
}
@@ -100,6 +109,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
/* accumulate */
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput*num_samples_inv, &L_light);
+ }
}
}
}
@@ -123,6 +135,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
/* accumulate */
path_radiance_accum_light(L, throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput*num_samples_adjust, &L_light);
+ }
}
}
}
@@ -130,9 +145,17 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
}
/* branched path tracing: bounce off or through surface to with new direction stored in ray */
-ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, const ShaderClosure *sc, int sample, int num_samples,
- float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
+ccl_device bool kernel_branched_path_surface_bounce(
+ KernelGlobals *kg,
+ RNG *rng,
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ int sample,
+ int num_samples,
+ ccl_addr_space float3 *throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L,
+ Ray *ray)
{
/* sample BSDF */
float bsdf_pdf;
@@ -189,7 +212,7 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
#endif
/* path tracing: connect path directly to position on a light and add it to L */
-ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_addr_space RNG *rng,
+ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
ShaderData *sd, ShaderData *emission_sd, float3 throughput, ccl_addr_space PathState *state,
PathRadiance *L)
{
@@ -197,6 +220,21 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_
if(!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)))
return;
+#ifdef __SHADOW_TRICKS__
+ if(state->flag & PATH_RAY_SHADOW_CATCHER) {
+ kernel_branched_path_surface_connect_light(kg,
+ rng,
+ sd,
+ emission_sd,
+ state,
+ throughput,
+ 1.0f,
+ L,
+ 1);
+ return;
+ }
+#endif
+
/* sample illumination from lights to find path contribution */
float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
float light_u, light_v;
@@ -221,6 +259,9 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_
/* accumulate */
path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput, &L_light);
+ }
}
}
#endif
@@ -228,7 +269,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_
/* path tracing: bounce off or through surface to with new direction stored in ray */
ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
- ccl_addr_space RNG *rng,
+ RNG *rng,
ShaderData *sd,
ccl_addr_space float3 *throughput,
ccl_addr_space PathState *state,
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index 28e1b5ba98e..371f2c1c7cb 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -20,7 +20,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void kernel_path_volume_connect_light(
KernelGlobals *kg,
- ccl_addr_space RNG *rng,
+ RNG *rng,
ShaderData *sd,
ShaderData *emission_sd,
float3 throughput,
@@ -69,7 +69,7 @@ ccl_device
#endif
bool kernel_path_volume_bounce(
KernelGlobals *kg,
- ccl_addr_space RNG *rng,
+ RNG *rng,
ShaderData *sd,
ccl_addr_space float3 *throughput,
ccl_addr_space PathState *state,
@@ -117,10 +117,18 @@ bool kernel_path_volume_bounce(
return true;
}
-#ifdef __BRANCHED_PATH__
-ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, ShaderData *emission_sd, float3 throughput, PathState *state, PathRadiance *L,
- bool sample_all_lights, Ray *ray, const VolumeSegment *segment)
+#ifndef __SPLIT_KERNEL__
+ccl_device void kernel_branched_path_volume_connect_light(
+ KernelGlobals *kg,
+ RNG *rng,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ float3 throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L,
+ bool sample_all_lights,
+ Ray *ray,
+ const VolumeSegment *segment)
{
#ifdef __EMISSION__
if(!kernel_data.integrator.use_direct_light)
@@ -270,7 +278,7 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
}
#endif /* __EMISSION__ */
}
-#endif /* __BRANCHED_PATH__ */
+#endif /* __SPLIT_KERNEL__ */
#endif /* __VOLUME_SCATTER__ */
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index ad3fa32a809..485b7b84fc8 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -98,7 +98,7 @@ ccl_device uint sobol_lookup(const uint m, const uint frame, const uint ex, cons
return index;
}
-ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension)
+ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension)
{
#ifdef __CMJ__
if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
@@ -130,7 +130,7 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *
#endif
}
-ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy)
+ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy)
{
#ifdef __CMJ__
if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
@@ -147,7 +147,7 @@ ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *r
}
}
-ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, ccl_addr_space RNG *rng, int x, int y, float *fx, float *fy)
+ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, RNG *rng, int x, int y, float *fx, float *fy)
{
#ifdef __SOBOL_FULL_SCREEN__
uint px, py;
@@ -259,12 +259,12 @@ ccl_device uint lcg_init(uint seed)
* For branches in the path we must be careful not to reuse the same number
* in a sequence and offset accordingly. */
-ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension)
+ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension)
{
return path_rng_1D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension);
}
-ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension)
+ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension)
{
/* the rng_offset is not increased for transparent bounces. if we do then
* fully transparent objects can become subtly visible by the different
@@ -277,29 +277,29 @@ ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_ad
return path_rng_1D(kg, rng, state->sample, state->num_samples, rng_offset + dimension);
}
-ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
+ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
{
path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy);
}
-ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
+ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
{
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension);
}
-ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
+ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
{
int rng_offset = state->rng_offset + state->transparent_bounce*PRNG_BOUNCE_NUM;
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, rng_offset + dimension);
}
-ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
+ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
{
path_rng_2D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension, fx, fy);
}
/* Utitility functions to get light termination value, since it might not be needed in many cases. */
-ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state)
+ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state)
{
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
return path_state_rng_1D_for_decision(kg, rng, state, PRNG_LIGHT_TERMINATE);
@@ -307,7 +307,7 @@ ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_
return 0.0f;
}
-ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches)
+ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches)
{
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
return path_branched_rng_1D_for_decision(kg, rng, state, branch, num_branches, PRNG_LIGHT_TERMINATE);
@@ -315,7 +315,7 @@ ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, c
return 0.0f;
}
-ccl_device_inline void path_state_branch(PathState *state, int branch, int num_branches)
+ccl_device_inline void path_state_branch(ccl_addr_space PathState *state, int branch, int num_branches)
{
/* path is splitting into a branch, adjust so that each branch
* still gets a unique sample from the same sequence */
@@ -324,18 +324,9 @@ ccl_device_inline void path_state_branch(PathState *state, int branch, int num_b
state->num_samples = state->num_samples*num_branches;
}
-ccl_device_inline uint lcg_state_init(RNG *rng, const PathState *state, uint scramble)
-{
- return lcg_init(*rng + state->rng_offset + state->sample*scramble);
-}
-
-/* TODO(sergey): For until we can use generic address space from OpenCL 2.0. */
-
-ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space RNG *rng,
- const ccl_addr_space PathState *state,
- uint scramble)
+ccl_device_inline uint lcg_state_init(RNG *rng, int rng_offset, int sample, uint scramble)
{
- return lcg_init(*rng + state->rng_offset + state->sample*scramble);
+ return lcg_init(*rng + rng_offset + sample*scramble);
}
ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 93a92c63a40..163777b713e 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -516,7 +516,7 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd
float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
if(bsdf_pdf != 0.0f) {
- bsdf_eval_accum(result_eval, sc->type, eval*sc->weight);
+ bsdf_eval_accum(result_eval, sc->type, eval*sc->weight, 1.0f);
sum_pdf += bsdf_pdf*sc->sample_weight;
}
@@ -544,7 +544,8 @@ ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
float mis_weight = use_mis? power_heuristic(light_pdf, bsdf_pdf): 1.0f;
bsdf_eval_accum(result_eval,
sc->type,
- eval * sc->weight * mis_weight);
+ eval * sc->weight,
+ mis_weight);
}
}
}
@@ -576,7 +577,7 @@ void shader_bsdf_eval(KernelGlobals *kg,
_shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, -1, eval, 0.0f, 0.0f);
if(use_mis) {
float weight = power_heuristic(light_pdf, pdf);
- bsdf_eval_mul(eval, weight);
+ bsdf_eval_mis(eval, weight);
}
}
}
@@ -862,7 +863,7 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
/* Surface Evaluation */
-ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_space RNG *rng,
+ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
{
sd->num_closure = 0;
@@ -887,7 +888,7 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_
}
if(rng && (sd->flag & SD_BSDF_NEEDS_LCG)) {
- sd->lcg_state = lcg_state_init_addrspace(rng, state, 0xb4bc3953);
+ sd->lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0xb4bc3953);
}
}
@@ -944,7 +945,7 @@ ccl_device_inline void _shader_volume_phase_multi_eval(const ShaderData *sd, con
float3 eval = volume_phase_eval(sd, sc, omega_in, &phase_pdf);
if(phase_pdf != 0.0f) {
- bsdf_eval_accum(result_eval, sc->type, eval);
+ bsdf_eval_accum(result_eval, sc->type, eval, 1.0f);
sum_pdf += phase_pdf*sc->sample_weight;
}
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index 4efc6c8118d..0426e0a62c9 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -128,6 +128,7 @@ ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
+ const int skip_object,
Ray *ray,
Intersection *hits,
uint max_hits,
@@ -140,6 +141,7 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
const bool blocked = scene_intersect_shadow_all(kg,
ray,
hits,
+ skip_object,
max_hits,
&num_hits);
/* If no opaque surface found but we did find transparent hits,
@@ -216,6 +218,7 @@ ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
+ const int skip_object,
Ray *ray,
uint max_hits,
float3 *shadow)
@@ -250,6 +253,7 @@ ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
return shadow_blocked_transparent_all_loop(kg,
shadow_sd,
state,
+ skip_object,
ray,
hits,
max_hits,
@@ -274,13 +278,14 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
KernelGlobals *kg,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
+ const int skip_object,
Ray *ray,
Intersection *isect,
const bool blocked,
const bool is_transparent_isect,
float3 *shadow)
{
- if(blocked && is_transparent_isect) {
+ if((blocked && is_transparent_isect) || skip_object != OBJECT_NONE) {
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float3 Pend = ray->P + ray->D*ray->t;
int bounce = state->transparent_bounce;
@@ -306,6 +311,23 @@ ccl_device bool shadow_blocked_transparent_stepped_loop(
{
break;
}
+#ifdef __SHADOW_TRICKS__
+ if(skip_object != OBJECT_NONE) {
+ const int isect_object = (isect->object == PRIM_NONE)
+ ? kernel_tex_fetch(__prim_object, isect->prim)
+ : isect->object;
+ if(isect_object == skip_object) {
+ shader_setup_from_ray(kg, shadow_sd, isect, ray);
+ /* Move ray forward. */
+ ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng);
+ if(ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
+ continue;
+ }
+ }
+#endif
if(!shader_transparent_shadow(kg, isect)) {
return true;
}
@@ -351,22 +373,31 @@ ccl_device bool shadow_blocked_transparent_stepped(
KernelGlobals *kg,
ShaderData *shadow_sd,
ccl_addr_space PathState *state,
+ const int skip_object,
Ray *ray,
Intersection *isect,
float3 *shadow)
{
- const bool blocked = scene_intersect(kg,
- *ray,
- PATH_RAY_SHADOW_OPAQUE,
- isect,
- NULL,
- 0.0f, 0.0f);
- const bool is_transparent_isect = blocked
- ? shader_transparent_shadow(kg, isect)
- : false;
+ bool blocked, is_transparent_isect;
+ if (skip_object == OBJECT_NONE) {
+ blocked = scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+ is_transparent_isect = blocked
+ ? shader_transparent_shadow(kg, isect)
+ : false;
+ }
+ else {
+ blocked = false;
+ is_transparent_isect = false;
+ }
return shadow_blocked_transparent_stepped_loop(kg,
shadow_sd,
state,
+ skip_object,
ray,
isect,
blocked,
@@ -390,12 +421,21 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
if(ray->t == 0.0f) {
return false;
}
+#ifdef __SHADOW_TRICKS__
+ const int skip_object = state->catcher_object;
+#else
+ const int skip_object = OBJECT_NONE;
+#endif
/* Do actual shadow shading. */
/* First of all, we check if integrator requires transparent shadows.
* if not, we use simplest and fastest ever way to calculate occlusion.
+ *
+ * NOTE: We can't do quick opaque test here if we are on shadow-catcher
+ * path because we don't want catcher object to be casting shadow here.
*/
#ifdef __TRANSPARENT_SHADOWS__
- if(!kernel_data.integrator.transparent_shadows)
+ if(!kernel_data.integrator.transparent_shadows &&
+ skip_object == OBJECT_NONE)
#endif
{
return shadow_blocked_opaque(kg,
@@ -440,6 +480,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
return shadow_blocked_transparent_stepped_loop(kg,
shadow_sd,
state,
+ skip_object,
ray,
&isect,
blocked,
@@ -450,6 +491,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
return shadow_blocked_transparent_all(kg,
shadow_sd,
state,
+ skip_object,
ray,
max_hits,
shadow);
@@ -458,6 +500,7 @@ ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
return shadow_blocked_transparent_stepped(kg,
shadow_sd,
state,
+ skip_object,
ray,
&isect,
shadow);
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index 64d240d779d..f75e9337bdb 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -223,7 +223,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
SubsurfaceIntersection *ss_isect,
ShaderData *sd,
ShaderClosure *sc,
- uint *lcg_state,
+ RNG *lcg_state,
float disk_u,
float disk_v,
bool all)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 245832ae163..1ae624e06c5 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -157,6 +157,7 @@ CCL_NAMESPACE_BEGIN
#define __INTERSECTION_REFINE__
#define __CLAMP_SAMPLE__
#define __PATCH_EVAL__
+#define __SHADOW_TRICKS__
#ifdef __KERNEL_SHADING__
# define __SVM__
@@ -212,6 +213,9 @@ CCL_NAMESPACE_BEGIN
#ifdef __NO_TRANSPARENT__
# undef __TRANSPARENT_SHADOWS__
#endif
+#ifdef __NO_SHADOW_TRICKS__
+#undef __SHADOW_TRICKS__
+#endif
/* Random Numbers */
@@ -316,6 +320,8 @@ enum PathRayFlag {
PATH_RAY_MIS_SKIP = 4096,
PATH_RAY_DIFFUSE_ANCESTOR = 8192,
PATH_RAY_SINGLE_PASS_DONE = 16384,
+ PATH_RAY_SHADOW_CATCHER = 32768,
+ PATH_RAY_SHADOW_CATCHER_ONLY = 65536,
};
/* Closure Label */
@@ -445,6 +451,20 @@ typedef ccl_addr_space struct PathRadiance {
float4 shadow;
float mist;
#endif
+
+#ifdef __SHADOW_TRICKS__
+ /* Total light reachable across the path, ignoring shadow blocked queries. */
+ float3 path_total;
+ /* Total light reachable across the path with shadow blocked queries
+ * applied here.
+ *
+ * Dividing this figure by path_total will give estimate of shadow pass.
+ */
+ float3 path_total_shaded;
+
+ /* Color of the background on which shadow is alpha-overed. */
+ float3 shadow_color;
+#endif
} PathRadiance;
typedef struct BsdfEval {
@@ -460,6 +480,9 @@ typedef struct BsdfEval {
float3 subsurface;
float3 scatter;
#endif
+#ifdef __SHADOW_TRICKS__
+ float3 sum_no_mis;
+#endif
} BsdfEval;
/* Shader Flag */
@@ -805,13 +828,16 @@ enum ShaderDataObjectFlag {
SD_OBJECT_INTERSECTS_VOLUME = (1 << 5),
/* Has position for motion vertices. */
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6),
+ /* object is used to catch shadows */
+ SD_OBJECT_SHADOW_CATCHER = (1 << 7),
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK |
SD_OBJECT_MOTION |
SD_OBJECT_TRANSFORM_APPLIED |
SD_OBJECT_NEGATIVE_SCALE_APPLIED |
SD_OBJECT_HAS_VOLUME |
- SD_OBJECT_INTERSECTS_VOLUME)
+ SD_OBJECT_INTERSECTS_VOLUME |
+ SD_OBJECT_SHADOW_CATCHER)
};
typedef ccl_addr_space struct ShaderData {
@@ -930,6 +956,10 @@ typedef struct PathState {
RNG rng_congruential;
VolumeStack volume_stack[VOLUME_STACK_SIZE];
#endif
+
+#ifdef __SHADOW_TRICKS__
+ int catcher_object;
+#endif
} PathState;
/* Subsurface */
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index dcab138dc84..9c0878249d4 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -360,7 +360,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
ShaderData *sd,
PathRadiance *L,
ccl_addr_space float3 *throughput,
- ccl_addr_space RNG *rng,
+ RNG *rng,
bool probalistic_scatter)
{
VolumeShaderCoefficients coeff;
@@ -469,7 +469,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
ShaderData *sd,
PathRadiance *L,
ccl_addr_space float3 *throughput,
- ccl_addr_space RNG *rng)
+ RNG *rng)
{
float3 tp = *throughput;
const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
@@ -610,7 +610,7 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(
Ray *ray,
PathRadiance *L,
ccl_addr_space float3 *throughput,
- ccl_addr_space RNG *rng,
+ RNG *rng,
bool heterogeneous)
{
shader_setup_from_volume(kg, sd, ray);
diff --git a/intern/cycles/kernel/split/kernel_buffer_update.h b/intern/cycles/kernel/split/kernel_buffer_update.h
index f36899b884a..859c221d976 100644
--- a/intern/cycles/kernel/split/kernel_buffer_update.h
+++ b/intern/cycles/kernel/split/kernel_buffer_update.h
@@ -87,7 +87,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
ccl_global float *L_transparent = &kernel_split_state.L_transparent[ray_index];
- ccl_global uint *rng = &kernel_split_state.rng[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
ccl_global float *buffer = kernel_split_params.buffer;
unsigned int work_index;
@@ -111,7 +111,16 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
- float3 L_sum = path_radiance_clamp_and_sum(kg, L);
+ float3 L_sum;
+#ifdef __SHADOW_TRICKS__
+ if(state->flag & PATH_RAY_SHADOW_CATCHER) {
+ L_sum = path_radiance_sum_shadowcatcher(kg, L, L_transparent);
+ }
+ else
+#endif /* __SHADOW_TRICKS__ */
+ {
+ L_sum = path_radiance_clamp_and_sum(kg, L);
+ }
kernel_write_light_passes(kg, buffer, L, sample);
#ifdef __KERNEL_DEBUG__
kernel_write_debug_passes(kg, buffer, state, debug_data, sample);
@@ -120,7 +129,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
/* accumulate result in output buffer */
kernel_write_pass_float4(buffer, sample, L_rad);
- path_rng_end(kg, rng_state, *rng);
+ path_rng_end(kg, rng_state, rng);
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
}
@@ -146,7 +155,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
/* Initialize random numbers and ray. */
- kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, rng, ray);
+ kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, &rng, ray);
if(ray->t != 0.0f) {
/* Initialize throughput, L_transparent, Ray, PathState;
@@ -155,7 +164,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
*throughput = make_float3(1.0f, 1.0f, 1.0f);
*L_transparent = 0.0f;
path_radiance_init(L, kernel_data.film.use_light_pass);
- path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, rng, sample, ray);
+ path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &rng, sample, ray);
#ifdef __SUBSURFACE__
kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
#endif
@@ -170,12 +179,13 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
/* Accumulate result in output buffer. */
kernel_write_pass_float4(buffer, sample, L_rad);
- path_rng_end(kg, rng_state, *rng);
+ path_rng_end(kg, rng_state, rng);
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
}
}
}
+ kernel_split_state.rng[ray_index] = rng;
#ifndef __COMPUTE_DEVICE_GPU__
}
diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h
index 3d062cf0e2b..bdbf7387b95 100644
--- a/intern/cycles/kernel/split/kernel_direct_lighting.h
+++ b/intern/cycles/kernel/split/kernel_direct_lighting.h
@@ -79,15 +79,32 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
/* direct lighting */
#ifdef __EMISSION__
- if((kernel_data.integrator.use_direct_light &&
- (sd->flag & SD_BSDF_HAS_EVAL)))
- {
+ RNG rng = kernel_split_state.rng[ray_index];
+ bool flag = (kernel_data.integrator.use_direct_light &&
+ (sd->flag & SD_BSDF_HAS_EVAL));
+# ifdef __SHADOW_TRICKS__
+ if(flag && state->flag & PATH_RAY_SHADOW_CATCHER) {
+ flag = false;
+ ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
+ float3 throughput = kernel_split_state.throughput[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ kernel_branched_path_surface_connect_light(kg,
+ &rng,
+ sd,
+ emission_sd,
+ state,
+ throughput,
+ 1.0f,
+ L,
+ 1);
+ }
+# endif /* __SHADOW_TRICKS__ */
+ if(flag) {
/* Sample illumination from lights to find path contribution. */
- ccl_global RNG* rng = &kernel_split_state.rng[ray_index];
- float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT);
float light_u, light_v;
- path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_state_rng_light_termination(kg, rng, state);
+ path_state_rng_2D(kg, &rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_state_rng_light_termination(kg, &rng, state);
LightSample ls;
if(light_sample(kg,
@@ -98,9 +115,9 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
&ls)) {
Ray light_ray;
-#ifdef __OBJECT_MOTION__
+# ifdef __OBJECT_MOTION__
light_ray.time = sd->time;
-#endif
+# endif
BsdfEval L_light;
bool is_lamp;
@@ -117,6 +134,7 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
}
}
}
+ kernel_split_state.rng[ray_index] = rng;
#endif /* __EMISSION__ */
}
diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h
index b1df45d6bb2..47d3c280831 100644
--- a/intern/cycles/kernel/split/kernel_do_volume.h
+++ b/intern/cycles/kernel/split/kernel_do_volume.h
@@ -50,7 +50,7 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- ccl_global RNG *rng = &kernel_split_state.rng[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
ShaderData *sd = &kernel_split_state.sd[ray_index];
ShaderData *sd_input = &kernel_split_state.sd_DL_shadow[ray_index];
@@ -69,15 +69,15 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
{
/* integrate along volume segment with distance sampling */
VolumeIntegrateResult result = kernel_volume_integrate(
- kg, state, sd, &volume_ray, L, throughput, rng, heterogeneous);
+ kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
/* direct lighting */
- kernel_path_volume_connect_light(kg, rng, sd, sd_input, *throughput, state, L);
+ kernel_path_volume_connect_light(kg, &rng, sd, sd_input, *throughput, state, L);
/* indirect light bounce */
- if(kernel_path_volume_bounce(kg, rng, sd, throughput, state, L, ray))
+ if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray))
ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED);
else
ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER);
@@ -85,6 +85,7 @@ ccl_device void kernel_do_volume(KernelGlobals *kg)
# endif
}
}
+ kernel_split_state.rng[ray_index] = rng;
}
#endif
diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
index 1834a791b91..9fc853a84bf 100644
--- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
+++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
@@ -98,7 +98,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
unsigned int tile_y;
unsigned int sample;
- ccl_global RNG *rng = 0x0;
+ RNG rng = kernel_split_state.rng[ray_index];
ccl_global PathState *state = 0x0;
float3 throughput;
@@ -110,7 +110,6 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
throughput = kernel_split_state.throughput[ray_index];
state = &kernel_split_state.path_state[ray_index];
- rng = &kernel_split_state.rng[ray_index];
work_index = kernel_split_state.work_array[ray_index];
sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
@@ -121,6 +120,23 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
buffer += (kernel_split_params.offset + pixel_x + pixel_y * stride) * kernel_data.film.pass_stride;
+#ifdef __SHADOW_TRICKS__
+ if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ if (state->flag & PATH_RAY_CAMERA) {
+ state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
+ state->catcher_object = sd->object;
+ if(!kernel_data.background.transparent) {
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ L->shadow_color = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray);
+ }
+ }
+ }
+ else {
+ state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
+
/* holdout */
#ifdef __HOLDOUT__
if(((sd->flag & SD_HOLDOUT) ||
@@ -194,7 +210,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
if(probability != 1.0f) {
- float terminate = path_state_rng_1D_for_decision(kg, rng, state, PRNG_TERMINATE);
+ float terminate = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_TERMINATE);
if(terminate >= probability) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
enqueue_flag = 1;
@@ -214,7 +230,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
{
/* todo: solve correlation */
float bsdf_u, bsdf_v;
- path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_state_rng_2D(kg, &rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float ao_factor = kernel_data.background.ao_factor;
float3 ao_N;
@@ -243,6 +259,8 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
}
}
#endif /* __AO__ */
+ kernel_split_state.rng[ray_index] = rng;
+
#ifndef __COMPUTE_DEVICE_GPU__
}
diff --git a/intern/cycles/kernel/split/kernel_indirect_background.h b/intern/cycles/kernel/split/kernel_indirect_background.h
index 100f5996f83..8192528622e 100644
--- a/intern/cycles/kernel/split/kernel_indirect_background.h
+++ b/intern/cycles/kernel/split/kernel_indirect_background.h
@@ -70,7 +70,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
#ifdef __BACKGROUND__
/* sample background shader */
float3 L_background = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray);
- path_radiance_accum_background(L, (*throughput), L_background, state->bounce);
+ path_radiance_accum_background(L, state, (*throughput), L_background);
#endif
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
}
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
index 056fb1d8c08..1bebc16e25b 100644
--- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h
+++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
@@ -117,6 +117,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
shadow,
state->bounce);
}
+ else {
+ path_radiance_accum_total_ao(L, _throughput, kernel_split_state.ao_bsdf[ray_index]);
+ }
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
}
@@ -124,8 +127,8 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
float3 shadow = kernel_split_state.light_ray[ray_index].P;
// TODO(mai): investigate correctness here
char update_path_radiance = (char)kernel_split_state.light_ray[ray_index].t;
+ BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
if(update_path_radiance) {
- BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
path_radiance_accum_light(L,
_throughput,
&L_light,
@@ -134,6 +137,9 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
state->bounce,
kernel_split_state.is_lamp[ray_index]);
}
+ else {
+ path_radiance_accum_total_light(L, _throughput, &L_light);
+ }
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
}
}
@@ -141,15 +147,16 @@ ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
- ccl_global RNG *rng = &kernel_split_state.rng[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
state = &kernel_split_state.path_state[ray_index];
L = &kernel_split_state.path_radiance[ray_index];
/* Compute direct lighting and next bounce. */
- if(!kernel_path_surface_bounce(kg, rng, &kernel_split_state.sd[ray_index], throughput, state, L, ray)) {
+ if(!kernel_path_surface_bounce(kg, &rng, &kernel_split_state.sd[ray_index], throughput, state, L, ray)) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
enqueue_flag = 1;
}
+ kernel_split_state.rng[ray_index] = rng;
}
#ifndef __COMPUTE_DEVICE_GPU__
diff --git a/intern/cycles/kernel/split/kernel_path_init.h b/intern/cycles/kernel/split/kernel_path_init.h
index f879fca5009..a7ecde7c80d 100644
--- a/intern/cycles/kernel/split/kernel_path_init.h
+++ b/intern/cycles/kernel/split/kernel_path_init.h
@@ -60,12 +60,14 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
ccl_global float *buffer = kernel_split_params.buffer;
buffer += (kernel_split_params.offset + pixel_x + pixel_y * kernel_split_params.stride) * kernel_data.film.pass_stride;
+ RNG rng = kernel_split_state.rng[ray_index];
+
/* Initialize random numbers and ray. */
kernel_path_trace_setup(kg,
rng_state,
my_sample,
pixel_x, pixel_y,
- &kernel_split_state.rng[ray_index],
+ &rng,
&kernel_split_state.ray[ray_index]);
if(kernel_split_state.ray[ray_index].t != 0.0f) {
@@ -78,7 +80,7 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
path_state_init(kg,
&kernel_split_state.sd_DL_shadow[ray_index],
&kernel_split_state.path_state[ray_index],
- &kernel_split_state.rng[ray_index],
+ &rng,
my_sample,
&kernel_split_state.ray[ray_index]);
#ifdef __SUBSURFACE__
@@ -97,6 +99,7 @@ ccl_device void kernel_path_init(KernelGlobals *kg) {
path_rng_end(kg, rng_state, kernel_split_state.rng[ray_index]);
ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE);
}
+ kernel_split_state.rng[ray_index] = rng;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h
index 66f549f59b7..684760eedee 100644
--- a/intern/cycles/kernel/split/kernel_scene_intersect.h
+++ b/intern/cycles/kernel/split/kernel_scene_intersect.h
@@ -72,7 +72,7 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(&rng, &state, 0x51633e2d);
+ lcg_state = lcg_state_init(&rng, state.rng_offset, state.sample, 0x51633e2d);
}
if(state.bounce > kernel_data.integrator.ao_bounces) {
diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h
index b739f86338c..0f1696e34a0 100644
--- a/intern/cycles/kernel/split/kernel_shader_eval.h
+++ b/intern/cycles/kernel/split/kernel_shader_eval.h
@@ -54,7 +54,7 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg,
/* Continue on with shader evaluation. */
if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
Intersection isect = kernel_split_state.isect[ray_index];
- ccl_global uint *rng = &kernel_split_state.rng[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
Ray ray = kernel_split_state.ray[ray_index];
@@ -62,8 +62,9 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg,
&kernel_split_state.sd[ray_index],
&isect,
&ray);
- float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
- shader_eval_surface(kg, &kernel_split_state.sd[ray_index], rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+ float rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
+ shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+ kernel_split_state.rng[ray_index] = rng;
}
}
diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
index 4eaa7f56332..0b4d50c70ee 100644
--- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h
+++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
@@ -55,7 +55,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg,
ccl_global char *ray_state = kernel_split_state.ray_state;
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
- ccl_global RNG *rng = &kernel_split_state.rng[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
ccl_global SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
@@ -69,7 +69,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg,
emission_sd,
L,
state,
- rng,
+ &rng,
ray,
throughput,
ss_indirect)) {
@@ -77,6 +77,7 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg,
enqueue_flag = 1;
}
}
+ kernel_split_state.rng[ray_index] = rng;
}
#ifndef __COMPUTE_DEVICE_GPU__
diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h
index a8b3604a8a7..9e826c8c23f 100644
--- a/intern/cycles/kernel/svm/svm_voxel.h
+++ b/intern/cycles/kernel/svm/svm_voxel.h
@@ -46,7 +46,7 @@ ccl_device void svm_node_tex_voxel(KernelGlobals *kg,
# if defined(__KERNEL_CUDA__)
# if __CUDA_ARCH__ >= 300
CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id);
- if(id < 2048) /* TODO(dingto): Make this a variable */
+ if(id < TEX_START_HALF4_CUDA_KEPLER)
r = kernel_tex_image_interp_3d_float4(tex, co.x, co.y, co.z);
else {
float f = kernel_tex_image_interp_3d_float(tex, co.x, co.y, co.z);
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index f6c83fb5c7e..0cfd08090c2 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -17,6 +17,7 @@
#include "attribute.h"
#include "graph.h"
#include "nodes.h"
+#include "scene.h"
#include "shader.h"
#include "constant_fold.h"
@@ -195,6 +196,7 @@ bool ShaderNode::equals(const ShaderNode& other)
ShaderGraph::ShaderGraph()
{
finalized = false;
+ simplified = false;
num_node_ids = 0;
add(new OutputNode());
}
@@ -207,6 +209,8 @@ ShaderGraph::~ShaderGraph()
ShaderNode *ShaderGraph::add(ShaderNode *node)
{
assert(!finalized);
+ simplified = false;
+
node->id = num_node_ids++;
nodes.push_back(node);
return node;
@@ -241,6 +245,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
{
assert(!finalized);
assert(from && to);
+ simplified = false;
if(to->link) {
fprintf(stderr, "Cycles shader graph connect: input already connected.\n");
@@ -273,6 +278,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
void ShaderGraph::disconnect(ShaderOutput *from)
{
assert(!finalized);
+ simplified = false;
foreach(ShaderInput *sock, from->links) {
sock->link = NULL;
@@ -285,6 +291,7 @@ void ShaderGraph::disconnect(ShaderInput *to)
{
assert(!finalized);
assert(to->link);
+ simplified = false;
ShaderOutput *from = to->link;
@@ -294,6 +301,8 @@ void ShaderGraph::disconnect(ShaderInput *to)
void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
{
+ simplified = false;
+
/* Copy because disconnect modifies this list */
vector<ShaderInput*> outputs = from->links;
@@ -310,9 +319,19 @@ void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
}
}
+void ShaderGraph::simplify(Scene *scene)
+{
+ if(!simplified) {
+ default_inputs(scene->shader_manager->use_osl());
+ clean(scene);
+ refine_bump_nodes();
+
+ simplified = true;
+ }
+}
+
void ShaderGraph::finalize(Scene *scene,
bool do_bump,
- bool do_osl,
bool do_simplify,
bool bump_in_object_space)
{
@@ -322,9 +341,7 @@ void ShaderGraph::finalize(Scene *scene,
* modified afterwards. */
if(!finalized) {
- default_inputs(do_osl);
- clean(scene);
- refine_bump_nodes();
+ simplify(scene);
if(do_bump)
bump_from_displacement(bump_in_object_space);
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 06524d3fa13..d22193d4e51 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -240,6 +240,7 @@ public:
list<ShaderNode*> nodes;
size_t num_node_ids;
bool finalized;
+ bool simplified;
ShaderGraph();
~ShaderGraph();
@@ -255,9 +256,9 @@ public:
void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
void remove_proxy_nodes();
+ void simplify(Scene *scene);
void finalize(Scene *scene,
bool do_bump = false,
- bool do_osl = false,
bool do_simplify = false,
bool bump_in_object_space = false);
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 8342f376836..a3a8c6d68e4 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -49,6 +49,8 @@ NODE_DEFINE(Object)
SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
+ SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
+
return type;
}
@@ -597,6 +599,12 @@ void ObjectManager::device_update_flags(Device *device,
else {
object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
}
+ if(object->is_shadow_catcher) {
+ object_flag[object_index] |= SD_OBJECT_SHADOW_CATCHER;
+ }
+ else {
+ object_flag[object_index] &= ~SD_OBJECT_SHADOW_CATCHER;
+ }
if(bounds_valid) {
foreach(Object *volume_object, volume_objects) {
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 3495849d149..dabe0f71662 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -53,6 +53,7 @@ public:
bool use_motion;
bool hide_on_missing_motion;
bool use_holdout;
+ bool is_shadow_catcher;
float3 dupli_generated;
float2 dupli_uv;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 67b68e63cb2..68bd8d96bf9 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -1096,12 +1096,10 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
/* finalize */
shader->graph->finalize(scene,
false,
- true,
shader->has_integrator_dependency);
if(shader->graph_bump) {
shader->graph_bump->finalize(scene,
true,
- true,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
}
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index e7050f9ef37..bd664b35e19 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -637,6 +637,9 @@ DeviceRequestedFeatures Session::get_requested_device_features()
requested_features.use_patch_evaluation = true;
}
#endif
+ if(object->is_shadow_catcher) {
+ requested_features.use_shadow_tricks = true;
+ }
}
BakeManager *bake_manager = scene->bake_manager;
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 955b892f4c3..bbf14c24b56 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -813,7 +813,6 @@ void SVMCompiler::compile(Scene *scene,
scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
shader->graph->finalize(scene,
false,
- false,
shader->has_integrator_dependency);
}
@@ -821,7 +820,6 @@ void SVMCompiler::compile(Scene *scene,
scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL);
shader->graph_bump->finalize(scene,
true,
- false,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
}
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 2af0e56325f..84a5c800357 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -774,6 +774,7 @@ template<size_t index_0, size_t index_1, size_t index_2, size_t index_3> __force
return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(index_3, index_2, index_1, index_0)));
}
+#if defined(__KERNEL_SSE3__)
template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b)
{
return _mm_moveldup_ps(b);
@@ -783,6 +784,7 @@ template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b)
{
return _mm_movehdup_ps(b);
}
+#endif
template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b)
{
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index ff1922af4f3..6887063eae9 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -908,6 +908,11 @@ extern int GHOST_UseNativePixels(void);
extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
/**
+ * Returns the suggested DPI for this window.
+ */
+extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle);
+
+/**
* Enable IME attached to the given window, i.e. allows user-input
* events to be dispatched to the IME.
* \param windowhandle Window handle of the caller
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 688ebecf557..4a4d6be5ced 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -332,6 +332,12 @@ public:
virtual float getNativePixelSize(void) = 0;
+ /**
+ * Returns the recommended DPI for this window.
+ * \return The recommended DPI for this window.
+ */
+ virtual GHOST_TUns16 getDPIHint() = 0;
+
#ifdef WITH_INPUT_IME
/**
* Enable IME attached to the given window, i.e. allows user-input
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 9ee4599a4a6..02b5063e515 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -189,6 +189,7 @@ typedef enum {
GHOST_kEventWindowUpdate,
GHOST_kEventWindowSize,
GHOST_kEventWindowMove,
+ GHOST_kEventWindowDPIHintChanged,
GHOST_kEventDraggingEntered,
GHOST_kEventDraggingUpdated,
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 41bc735e1e2..ce653188760 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -914,6 +914,12 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
return 1.0f;
}
+GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+ return window->getDPIHint();
+}
+
#ifdef WITH_INPUT_IME
void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 7d55a973f91..240d7ccd2fe 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -111,6 +111,11 @@
#define VK_MEDIA_PLAY_PAUSE 0xB3
#endif // VK_MEDIA_PLAY_PAUSE
+// Window message newer than Windows 7
+#ifndef WM_DPICHANGED
+#define WM_DPICHANGED 0x02E0
+#endif // WM_DPICHANGED
+
/* Workaround for some laptop touchpads, some of which seems to
* have driver issues which makes it so window function receives
* the message, but PeekMessage doesn't pick those messages for
@@ -152,6 +157,27 @@ static void initRawInput()
#undef DEVICE_COUNT
}
+#ifndef DPI_ENUMS_DECLARED
+typedef enum PROCESS_DPI_AWARENESS {
+ PROCESS_DPI_UNAWARE = 0,
+ PROCESS_SYSTEM_DPI_AWARE = 1,
+ PROCESS_PER_MONITOR_DPI_AWARE = 2
+} PROCESS_DPI_AWARENESS;
+
+typedef enum MONITOR_DPI_TYPE {
+ MDT_EFFECTIVE_DPI = 0,
+ MDT_ANGULAR_DPI = 1,
+ MDT_RAW_DPI = 2,
+ MDT_DEFAULT = MDT_EFFECTIVE_DPI
+} MONITOR_DPI_TYPE;
+
+#define USER_DEFAULT_SCREEN_DPI 96
+
+#define DPI_ENUMS_DECLARED
+#endif
+typedef HRESULT(API * GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
+typedef BOOL(API * GHOST_WIN32_EnableNonClientDpiScaling)(HWND);
+
GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
{
@@ -161,6 +187,18 @@ GHOST_SystemWin32::GHOST_SystemWin32()
m_consoleStatus = 1;
+ // Tell Windows we are per monitor DPI aware. This disables the default
+ // blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI.
+ HMODULE m_shcore = ::LoadLibrary("Shcore.dll");
+ if (m_shcore) {
+ GHOST_WIN32_SetProcessDpiAwareness fpSetProcessDpiAwareness =
+ (GHOST_WIN32_SetProcessDpiAwareness) ::GetProcAddress(m_shcore, "SetProcessDpiAwareness");
+
+ if (fpSetProcessDpiAwareness) {
+ fpSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
+ }
+ }
+
// Check if current keyboard layout uses AltGr and save keylayout ID for
// specialized handling if keys like VK_OEM_*. I.e. french keylayout
// generates VK_OEM_8 for their exclamation key (key left of right shift)
@@ -922,6 +960,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
if (hwnd) {
+ if(msg == WM_NCCREATE) {
+ // Tell Windows to automatically handle scaling of non-client areas
+ // such as the caption bar. EnableNonClientDpiScaling was introduced in Windows 10
+ HMODULE m_user32 = ::LoadLibrary("User32.dll");
+ if (m_user32) {
+ GHOST_WIN32_EnableNonClientDpiScaling fpEnableNonClientDpiScaling =
+ (GHOST_WIN32_EnableNonClientDpiScaling) ::GetProcAddress(m_user32, "EnableNonClientDpiScaling");
+
+ if (fpEnableNonClientDpiScaling) {
+ fpEnableNonClientDpiScaling(hwnd);
+ }
+ }
+ }
+
GHOST_WindowWin32 *window = (GHOST_WindowWin32 *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (window) {
switch (msg) {
@@ -1294,6 +1346,32 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
+ case WM_DPICHANGED:
+ /* The WM_DPICHANGED message is sent when the effective dots per inch (dpi) for a window has changed.
+ * The DPI is the scale factor for a window. There are multiple events that can cause the DPI to
+ * change such as when the window is moved to a monitor with a different DPI.
+ */
+ {
+ WORD newYAxisDPI = HIWORD(wParam);
+ WORD newXAxisDPI = LOWORD(wParam);
+ // The suggested new size and position of the window.
+ RECT* const suggestedWindowRect = (RECT*)lParam;
+
+ // Push DPI change event first
+ system->pushEvent(processWindowEvent(GHOST_kEventWindowDPIHintChanged, window));
+ system->dispatchEvents();
+ eventHandled = true;
+
+ // Then move and resize window
+ SetWindowPos(hwnd,
+ NULL,
+ suggestedWindowRect->left,
+ suggestedWindowRect->top,
+ suggestedWindowRect->right - suggestedWindowRect->left,
+ suggestedWindowRect->bottom - suggestedWindowRect->top,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ break;
////////////////////////////////////////////////////////////////////////
// Window events, ignored
////////////////////////////////////////////////////////////////////////
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index d778628ea37..2798bdf72f3 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -295,6 +295,15 @@ public:
return 1.0f;
}
+ /**
+ * Returns the recommended DPI for this window.
+ * \return The recommended DPI for this window.
+ */
+ virtual inline GHOST_TUns16 getDPIHint()
+ {
+ return 96;
+ }
+
#ifdef WITH_INPUT_IME
virtual void beginIME(GHOST_TInt32 x,
GHOST_TInt32 y,
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index 1335c38d977..aeb6188daef 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -563,3 +563,19 @@ GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
SDL_ShowCursor(visible);
return GHOST_kSuccess;
}
+
+GHOST_TUns16
+GHOST_WindowSDL::getDPIHint()
+{
+ int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win);
+ if (displayIndex < 0) {
+ return 96;
+ }
+
+ float ddpi;
+ if (SDL_GetDisplayDPI(displayIndex, &ddpi, NULL, NULL) != 0) {
+ return 96;
+ }
+
+ return (int)ddpi;
+}
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index 5f658e8ad01..96104ec28b4 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -168,6 +168,8 @@ protected:
GHOST_TSuccess beginFullScreen() const { return GHOST_kFailure; }
GHOST_TSuccess endFullScreen() const { return GHOST_kFailure; }
+
+ GHOST_TUns16 getDPIHint();
};
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 58aa0b87045..2c82e3a3f71 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -92,6 +92,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_tablet(0),
m_maxPressure(0),
m_normal_state(GHOST_kWindowStateNormal),
+ m_user32(NULL),
m_parentWindowHwnd(parentwindowhwnd),
m_debug_context(is_debug)
{
@@ -905,6 +906,23 @@ void GHOST_WindowWin32::bringTabletContextToFront()
}
}
+GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
+{
+ if (!m_user32) {
+ m_user32 = ::LoadLibrary("user32.dll");
+ }
+
+ if (m_user32) {
+ GHOST_WIN32_GetDpiForWindow fpGetDpiForWindow = (GHOST_WIN32_GetDpiForWindow) ::GetProcAddress(m_user32, "GetDpiForWindow");
+
+ if (fpGetDpiForWindow) {
+ return fpGetDpiForWindow(this->m_hWnd);
+ }
+ }
+
+ return USER_DEFAULT_SCREEN_DPI;
+}
+
/** Reverse the bits in a GHOST_TUns8 */
static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
{
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index a1cf58c9ceb..75a33951ff4 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -58,6 +58,12 @@ typedef BOOL (API * GHOST_WIN32_WTClose)(HCTX);
typedef BOOL (API * GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
typedef BOOL (API * GHOST_WIN32_WTOverlap)(HCTX, BOOL);
+// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions
+typedef UINT(API * GHOST_WIN32_GetDpiForWindow)(HWND);
+#ifndef USER_DEFAULT_SCREEN_DPI
+#define USER_DEFAULT_SCREEN_DPI 96
+#endif // USER_DEFAULT_SCREEN_DPI
+
/**
* GHOST window on M$ Windows OSs.
* \author Maarten Gribnau
@@ -251,6 +257,8 @@ public:
GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;}
+ GHOST_TUns16 getDPIHint() override;
+
/** if the window currently resizing */
bool m_inLiveResize;
@@ -351,6 +359,9 @@ private:
GHOST_TWindowState m_normal_state;
+ /** user32 dll handle*/
+ HMODULE m_user32;
+
/** Hwnd to parent window */
GHOST_TEmbedderWindowID m_parentWindowHwnd;
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 8cee785cdf6..f39f4f52289 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -56,6 +56,9 @@
# include <X11/extensions/XInput2.h>
#endif
+//For DPI value
+#include <X11/Xresource.h>
+
#if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
# include <strings.h>
#endif
@@ -68,6 +71,7 @@
#include <algorithm>
#include <string>
+#include <math.h>
/* For obscure full screen mode stuff
* lifted verbatim from blut. */
@@ -1661,3 +1665,44 @@ endFullScreen() const
return GHOST_kSuccess;
}
+
+GHOST_TUns16
+GHOST_WindowX11::
+getDPIHint()
+{
+ /* Try to read DPI setting set using xrdb */
+ char* resMan = XResourceManagerString(m_display);
+ if (resMan) {
+ XrmDatabase xrdb = XrmGetStringDatabase(resMan);
+ if (xrdb) {
+ char* type = NULL;
+ XrmValue val;
+
+ int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val);
+ if (success && type) {
+ if (strcmp(type, "String") == 0) {
+ return atoi((char*)val.addr);
+ }
+ }
+ }
+ }
+
+ /* Fallback to calculating DPI using X reported DPI, set using xrandr --dpi */
+ XWindowAttributes attr;
+ if (!XGetWindowAttributes(m_display, m_window, &attr)) {
+ /* Failed to get window attributes, return X11 default DPI */
+ return 96;
+ }
+
+ Screen* screen = attr.screen;
+ int pixelWidth = WidthOfScreen(screen);
+ int pixelHeight = HeightOfScreen(screen);
+ int mmWidth = WidthMMOfScreen(screen);
+ int mmHeight = HeightMMOfScreen(screen);
+
+ double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight));
+ double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight));
+ float inchDiagonal = mmDiagonal * 0.039f;
+ int dpi = pixelDiagonal / inchDiagonal;
+ return dpi;
+}
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 9380aa9d631..5c54c1e8162 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -235,6 +235,8 @@ public:
GHOST_TSuccess endFullScreen() const;
+ GHOST_TUns16 getDPIHint();
+
protected:
/**
* \param type The type of rendering context create.