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
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/kernel/kernel_path.h')
-rw-r--r--intern/cycles/kernel/kernel_path.h99
1 files changed, 94 insertions, 5 deletions
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index b073cd49a8c..815eb4a1d53 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -162,6 +162,86 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
return average(throughput);
}
+#ifdef __TRANSPARENT_SHADOWS__
+__device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
+{
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ float4 Ns = kernel_tex_fetch(__tri_normal, prim);
+ int shader = __float_as_int(Ns.w);
+
+ /* todo: add shader flag to check this */
+
+ return true;
+}
+#endif
+
+__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L)
+{
+ if(ray->t == 0.0f)
+ return false;
+
+ bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW, isect);
+
+#ifdef __TRANSPARENT_SHADOWS__
+ if(result && kernel_data.integrator.transparent_shadows) {
+ /* transparent shadows work in such a way to try to minimize overhead
+ in cases where we don't need them. after a regular shadow ray is
+ cast we check if the hit primitive was potentially transparent, and
+ only in that case start marching. this gives on extra ray cast for
+ the cases were we do want transparency */
+ if(shader_transparent_shadow(kg, isect)) {
+ /* todo: fix double contribution from indirect for triangle lights */
+ /* if(kernel_data.integrator.transparent_shadows && (path_flag & PATH_RAY_TRANSPARENT)) */
+
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D*ray->t;
+ int bounce = state->transparent_bounce;
+
+ for(;;) {
+ if(bounce >= kernel_data.integrator.transparent_max_bounce) {
+ return true;
+ }
+ else if(bounce >= kernel_data.integrator.transparent_min_bounce) {
+ /* todo: get random number somewhere for probabilistic terminate */
+#if 0
+ float probability = average(throughput);
+ float terminate = 0.0f; /* todo: get this random number */
+
+ if(terminate >= probability)
+ return true;
+
+ throughput /= probability;
+#endif
+ }
+
+ /* todo: fix it so we get first hit */
+ if(!scene_intersect(kg, ray, PATH_RAY_SHADOW, isect)) {
+ *light_L *= throughput;
+ return false;
+ }
+ if(!shader_transparent_shadow(kg, isect))
+ return true;
+
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, isect, ray);
+ shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW); /* todo: state flag? */
+
+ throughput *= shader_bsdf_transparency(kg, &sd);
+
+ ray->P = ray_offset(sd.P, -sd.Ng);
+ ray->t = len(Pend - ray->P);
+
+ bounce++;
+ }
+
+ return true;
+ }
+ }
+#endif
+
+ return result;
+}
+
__device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput)
{
/* initialize */
@@ -247,13 +327,22 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray
Ray light_ray;
float3 light_L;
- /* todo: use visbility flag to skip lights */
+#ifdef __MULTI_LIGHT__
+ /* index -1 means randomly sample from distribution */
+ int i = (kernel_data.integrator.num_distribution)? -1: 0;
- if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
- /* trace shadow ray */
- if(!scene_intersect(kg, &light_ray, PATH_RAY_SHADOW, &isect))
- L += throughput*light_L;
+ for(; i < kernel_data.integrator.num_all_lights; i++) {
+#else
+ const int i = -1;
+#endif
+ if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
+ /* trace shadow ray */
+ if(!shadow_blocked(kg, &state, &light_ray, &isect, &light_L))
+ L += throughput*light_L;
+ }
+#ifdef __MULTI_LIGHT__
}
+#endif
}
}
#endif