[Bf-blender-cvs] [e636d7f7eb0] soc-2020-production-ready-light-tree: Initial volume support in light tree.
Sam Kottler
noreply at git.blender.org
Tue Jul 21 22:01:36 CEST 2020
Commit: e636d7f7eb0ec5dbd8d84453b30e603e765b0378
Author: Sam Kottler
Date: Tue Jul 21 13:59:26 2020 -0600
Branches: soc-2020-production-ready-light-tree
https://developer.blender.org/rBe636d7f7eb0ec5dbd8d84453b30e603e765b0378
Initial volume support in light tree.
===================================================================
M intern/cycles/kernel/kernel_bake.h
M intern/cycles/kernel/kernel_emission.h
M intern/cycles/kernel/kernel_light.h
M intern/cycles/kernel/kernel_path.h
M intern/cycles/kernel/kernel_path_branched.h
M intern/cycles/kernel/kernel_path_surface.h
M intern/cycles/kernel/kernel_path_volume.h
M intern/cycles/kernel/kernel_types.h
M intern/cycles/kernel/kernel_volume.h
M intern/cycles/kernel/split/kernel_direct_lighting.h
M intern/cycles/kernel/split/kernel_do_volume.h
===================================================================
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index dde8f0b1a1b..8829df4d323 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -85,6 +85,7 @@ ccl_device_noinline void compute_light_pass(
kernel_path_subsurface_setup_indirect(kg, &ss_indirect, &state, &ray, L, &throughput);
indirect_sd.P_pick = sd->P_pick;
indirect_sd.N_pick = sd->N_pick;
+ indirect_sd.t_pick = sd->t_pick;
kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
}
is_sss_sample = true;
@@ -103,6 +104,7 @@ ccl_device_noinline void compute_light_pass(
/* compute indirect light */
indirect_sd.P_pick = sd->P_pick;
indirect_sd.N_pick = sd->N_pick;
+ indirect_sd.t_pick = sd->t_pick;
kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L);
/* sum and reset indirect light pass variables for the next samples */
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 46ff209e6f1..4a6c3796fec 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -228,7 +228,12 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg,
/* multiple importance sampling, get triangle light pdf,
* and compute weight with respect to BSDF pdf */
float pdf = triangle_light_pdf(kg, sd, t);
- pdf *= light_distribution_pdf(kg, P, N, sd->prim, sd->object, has_volume);
+ if ((path_flag & PATH_RAY_VOLUME_SCATTER) && sd->t_pick > 0.0f) {
+ pdf *= light_distribution_pdf(kg, sd->P_pick, sd->N_pick, sd->t_pick, sd->prim, sd->object);
+ }
+ else {
+ pdf *= light_distribution_pdf(kg, P, N, -1.0f, sd->prim, sd->object);
+ }
float mis_weight = power_heuristic(bsdf_pdf, pdf);
return L * mis_weight;
@@ -269,7 +274,6 @@ ccl_device_noinline_cpu void indirect_lamp_emission(KernelGlobals *kg,
float3 lamp_L = direct_emissive_eval(
kg, emission_sd, &ls, state, -ray->D, ray->dD, ls.t, ray->time);
- bool has_volume = false;
#ifdef __VOLUME__
if (state->volume_stack[0].shader != SHADER_NONE) {
/* shadow attenuation */
@@ -280,7 +284,6 @@ ccl_device_noinline_cpu void indirect_lamp_emission(KernelGlobals *kg,
lamp_L *= volume_tp;
}
- has_volume = ((emission_sd->flag & SD_HAS_VOLUME) != 0);
#endif
if (!(state->flag & PATH_RAY_MIS_SKIP)) {
@@ -288,7 +291,13 @@ ccl_device_noinline_cpu void indirect_lamp_emission(KernelGlobals *kg,
* and compute weight with respect to BSDF pdf */
/* multiply with light picking probablity to pdf */
- ls.pdf *= light_distribution_pdf(kg, ray->P, N, ~ls.lamp, -1, has_volume);
+ if ((state->flag & PATH_RAY_VOLUME_SCATTER) && emission_sd->t_pick > 0.0f) {
+ ls.pdf *= light_distribution_pdf(
+ kg, emission_sd->P_pick, emission_sd->N_pick, emission_sd->t_pick, ~ls.lamp, -1);
+ }
+ else {
+ ls.pdf *= light_distribution_pdf(kg, ray->P, N, -1.0f, ~ls.lamp, -1);
+ }
float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
lamp_L *= mis_weight;
}
@@ -321,11 +330,6 @@ ccl_device_noinline_cpu float3 indirect_background(KernelGlobals *kg,
return make_float3(0.0f, 0.0f, 0.0f);
}
- bool has_volume = false;
-# if defined(__BACKGROUND_MIS__) && defined(__VOLUME__)
- /* This has to be done before shader_setup_* below. */
- has_volume = ((emission_sd->flag & SD_HAS_VOLUME) != 0);
-# endif
/* Evaluate background shader. */
float3 L = make_float3(0.0f, 0.0f, 0.0f);
if (!shader_constant_emission_eval(kg, shader, &L)) {
@@ -360,7 +364,7 @@ ccl_device_noinline_cpu float3 indirect_background(KernelGlobals *kg,
* direction, and compute weight with respect to BSDF pdf */
float pdf = background_light_pdf(kg, P_pick, ray->D);
int background_index = kernel_data.integrator.background_light_index;
- pdf *= light_distribution_pdf(kg, P_pick, N_pick, ~background_index, -1, has_volume);
+ pdf *= light_distribution_pdf(kg, P_pick, N_pick, -1.0f, ~background_index, -1);
float mis_weight = power_heuristic(state->ray_pdf, pdf);
return L * mis_weight;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index b05bdde8d43..41afe50b41a 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -44,8 +44,16 @@ typedef struct LightSample {
* importance calculations or to flip the normal if we know it must refract. */
ccl_device void kernel_update_light_picking(KernelGlobals *kg,
ShaderData *sd,
- ccl_addr_space PathState *state)
+ ccl_addr_space PathState *state,
+ Ray *ray)
{
+ if (ray) {
+ sd->P_pick = ray->P + ray->D * ray->t;
+ sd->N_pick = -ray->D;
+ sd->t_pick = ray->t;
+ return;
+ }
+ sd->t_pick = -1.0f;
bool transmission = false;
bool reflective = false;
bool glass = false;
@@ -1172,44 +1180,21 @@ ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals *kg, int i
return (bounce > kernel_tex_fetch(__lights, index).max_bounces);
}
-/* calculates the importance metric for the given node and shading point P */
-ccl_device float calc_importance(KernelGlobals *kg,
- float3 P,
- float3 N,
- float3 bboxMax,
- float3 bboxMin,
- float theta_o,
- float theta_e,
- float3 axis,
- float energy,
- float3 centroid)
+ccl_device float calc_bbox_solid_angle(float3 P,
+ float3 centroid_to_P_dir,
+ float3 bboxMin,
+ float3 bboxMax)
{
- /* eq. 3 */
-
- const float3 centroid_to_P = P - centroid;
- const float3 centroid_to_P_dir = normalize(centroid_to_P);
- const float r2 = len_squared(bboxMax - centroid);
- float d2 = len_squared(centroid_to_P);
-
- /* based on comment in the implementation details of the paper */
- const bool splitting = kernel_data.integrator.splitting_threshold != 0.0f;
- if (!splitting) {
- d2 = fmaxf(d2, r2 * 0.25f);
- }
-
- /* "theta_u captures the solid angle of the entire box" */
-
- float theta_u;
if (P.x < bboxMax.x && P.y < bboxMax.y && P.z < bboxMax.z && P.x > bboxMin.x &&
P.y > bboxMin.y && P.z > bboxMin.z) {
/* P is inside bounding box */
- theta_u = M_PI_F;
+ return M_PI_F;
}
else {
/* Find the smallest cone that contains the bounding box by checking which bbox vertex is
* farthest out. If we use a bounding sphere we get a too big cone. For example consider a long
* skinny bbox oriented with P next to one of the small sides. */
- theta_u = 0;
+ float theta_u = 0;
float3 corners[8];
corners[0] = bboxMin;
corners[1] = make_float3(bboxMin.x, bboxMin.y, bboxMax.z);
@@ -1224,32 +1209,106 @@ ccl_device float calc_importance(KernelGlobals *kg,
const float cos_theta_u = dot(-centroid_to_P_dir, P_to_corner);
theta_u = fmaxf(fast_acosf(cos_theta_u), theta_u);
}
+ return theta_u;
}
+}
- /* cos(theta') */
- float cos_theta = dot(axis, centroid_to_P_dir);
- const float theta = fast_acosf(cos_theta);
- const float theta_prime = fmaxf(theta - theta_o - theta_u, 0.0f);
- if (theta_prime >= theta_e) {
- return 0.0f;
- }
- const float cos_theta_prime = fast_cosf(theta_prime);
-
- /* f_a|cos(theta'_i)| -- diffuse approximation */
- if (N != make_float3(0.0f, 0.0f, 0.0f)) {
- const float cos_theta_i = dot(N, -centroid_to_P_dir);
- const float theta_i = fast_acosf(cos_theta_i);
- const float theta_i_prime = fmaxf(theta_i - theta_u, 0.0f);
- const float cos_theta_i_prime = fast_cosf(theta_i_prime);
- const float abs_cos_theta_i_prime = fabsf(cos_theta_i_prime);
- /* doing something similar to bsdf_diffuse_eval_reflect() */
- /* TODO: Use theta_i or theta_i_prime here? */
- const float f_a = fmaxf(cos_theta_i_prime, 0.0f) * M_1_PI_F;
-
- return f_a * abs_cos_theta_i_prime * energy * cos_theta_prime / d2;
+/* calculates the importance metric for the given node and shading point P */
+ccl_device float calc_importance(KernelGlobals *kg,
+ float t_max,
+ float3 P,
+ float3 N,
+ float3 bboxMax,
+ float3 bboxMin,
+ float theta_o,
+ float theta_e,
+ float3 axis,
+ float energy,
+ float3 centroid)
+{
+ if (t_max < 0.0f) {
+ /* eq. 3 */
+
+ const float3 centroid_to_P = P - centroid;
+ const float3 centroid_to_P_dir = normalize(centroid_to_P);
+ const float r2 = len_squared(bboxMax - centroid);
+ float d2 = len_squared(centroid_to_P);
+
+ /* based on comment in the implementation details of the paper */
+ const bool splitting = kernel_data.integrator.splitting_threshold != 0.0f;
+ if (!splitting) {
+ d2 = fmaxf(d2, r2 * 0.25f);
+ }
+
+ /* "theta_u captures the solid angle of the entire box" */
+
+ float theta_u = calc_bbox_solid_angle(P, centroid_to_P_dir, bboxMin, bboxMax);
+
+ /* cos(theta') */
+ float cos_theta = dot(axis, centroid_to_P_dir);
+ const float theta = fast_acosf(cos_theta);
+ const float theta_prime = fmaxf(theta - theta_o - theta_u, 0.0f);
+ if (theta_prime >= theta_e) {
+ return 0.0f;
+ }
+ const float cos_theta_prime = fast_cosf(theta_prime);
+
+ /* f_a|cos(theta'_i)| -- diffuse approximation */
+ if (N != make_float3(0.0f, 0.0f, 0.0f))
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list