Merge branch 'master' into blender2.8

This commit is contained in:
Campbell Barton 2017-09-13 23:44:13 +10:00
commit 37d8d4787c
45 changed files with 1045 additions and 1165 deletions

@ -53,7 +53,11 @@ echo "OK"
# Create the tarball
cd "$blender_srcdir"
echo -n "Creating archive: \"$BASE_DIR/$TARBALL\" ..."
GZIP=-9 tar --transform "s,^,blender-$VERSION/,g" -zcf "$BASE_DIR/$TARBALL" -T "$BASE_DIR/$MANIFEST"
tar --transform "s,^,blender-$VERSION/,g" \
--use-compress-program="gzip --best" \
--create \
--file="$BASE_DIR/$TARBALL" \
--files-from="$BASE_DIR/$MANIFEST"
echo "OK"

@ -348,8 +348,9 @@ ccl_device_inline Bssrdf *bssrdf_alloc(ShaderData *sd, float3 weight)
{
Bssrdf *bssrdf = (Bssrdf*)closure_alloc(sd, sizeof(Bssrdf), CLOSURE_NONE_ID, weight);
if(!bssrdf)
if(bssrdf == NULL) {
return NULL;
}
float sample_weight = fabsf(average(weight));
bssrdf->sample_weight = sample_weight;

@ -226,9 +226,9 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
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_background_color = make_float3(0.0f, 0.0f, 0.0f);
L->shadow_radiance_sum = make_float3(0.0f, 0.0f, 0.0f);
L->shadow_throughput = 0.0f;
L->shadow_transparency = 1.0f;
L->has_shadow_catcher = 0;
#endif
#ifdef __DENOISING_FEATURES__
@ -279,13 +279,22 @@ ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space
}
}
ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce)
ccl_device_inline void path_radiance_accum_emission(PathRadiance *L,
ccl_addr_space PathState *state,
float3 throughput,
float3 value)
{
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_SHADOW_CATCHER) {
return;
}
#endif
#ifdef __PASSES__
if(L->use_light_pass) {
if(bounce == 0)
if(state->bounce == 0)
L->emission += throughput*value;
else if(bounce == 1)
else if(state->bounce == 1)
L->direct_emission += throughput*value;
else
L->indirect += throughput*value;
@ -304,6 +313,18 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L,
float3 bsdf,
float3 ao)
{
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
float3 light = throughput * bsdf;
L->path_total += light;
L->path_total_shaded += ao * light;
if(state->flag & PATH_RAY_SHADOW_CATCHER) {
return;
}
}
#endif
#ifdef __PASSES__
if(L->use_light_pass) {
if(state->bounce == 0) {
@ -321,14 +342,6 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L,
{
L->emission += throughput*bsdf*ao;
}
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
float3 light = throughput * bsdf;
L->path_total += light;
L->path_total_shaded += ao * light;
}
#endif
}
ccl_device_inline void path_radiance_accum_total_ao(
@ -357,6 +370,18 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L,
float shadow_fac,
bool is_lamp)
{
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
float3 light = throughput * bsdf_eval->sum_no_mis;
L->path_total += light;
L->path_total_shaded += shadow * light;
if(state->flag & PATH_RAY_SHADOW_CATCHER) {
return;
}
}
#endif
#ifdef __PASSES__
if(L->use_light_pass) {
if(state->bounce == 0) {
@ -383,14 +408,6 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L,
{
L->emission += throughput*bsdf_eval->diffuse*shadow;
}
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
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(
@ -417,6 +434,18 @@ ccl_device_inline void path_radiance_accum_background(
float3 throughput,
float3 value)
{
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
L->path_total += throughput * value;
L->path_total_shaded += throughput * value * L->shadow_transparency;
if(state->flag & PATH_RAY_SHADOW_CATCHER) {
return;
}
}
#endif
#ifdef __PASSES__
if(L->use_light_pass) {
if(state->bounce == 0)
@ -432,18 +461,31 @@ ccl_device_inline void path_radiance_accum_background(
L->emission += throughput*value;
}
#ifdef __SHADOW_TRICKS__
if(state->flag & PATH_RAY_STORE_SHADOW_INFO) {
L->path_total += throughput * value;
L->path_total_shaded += throughput * value * L->shadow_transparency;
}
#endif
#ifdef __DENOISING_FEATURES__
L->denoising_albedo += state->denoising_feature_weight * value;
#endif /* __DENOISING_FEATURES__ */
}
ccl_device_inline void path_radiance_accum_transparent(
PathRadiance *L,
ccl_addr_space PathState *state,
float3 throughput)
{
L->transparent += average(throughput);
}
#ifdef __SHADOW_TRICKS__
ccl_device_inline void path_radiance_accum_shadowcatcher(
PathRadiance *L,
float3 throughput,
float3 background)
{
L->shadow_throughput += average(throughput);
L->shadow_background_color += throughput * background;
L->has_shadow_catcher = 1;
}
#endif
ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
{
#ifdef __PASSES__
@ -501,7 +543,36 @@ ccl_device_inline void path_radiance_copy_indirect(PathRadiance *L,
#endif
}
ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L)
#ifdef __SHADOW_TRICKS__
ccl_device_inline void path_radiance_sum_shadowcatcher(KernelGlobals *kg,
PathRadiance *L,
float3 *L_sum,
float *alpha)
{
/* Calculate current shadow of the path. */
float path_total = average(L->path_total);
float shadow;
if(path_total == 0.0f) {
shadow = L->shadow_transparency;
}
else {
float path_total_shaded = average(L->path_total_shaded);
shadow = path_total_shaded / path_total;
}
/* Calculate final light sum and transparency for shadow catcher object. */
if(kernel_data.background.transparent) {
*alpha -= L->shadow_throughput * shadow;
}
else {
L->shadow_background_color *= shadow;
*L_sum += L->shadow_background_color;
}
}
#endif
ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L, float *alpha)
{
float3 L_sum;
/* Light Passes are used */
@ -578,8 +649,6 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
L_sum = L_direct + L_indirect;
}
#endif
return L_sum;
}
/* No Light Passes */
@ -587,14 +656,24 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
#endif
{
L_sum = L->emission;
/* Reject invalid value */
float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
if(!isfinite_safe(sum)) {
kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
L_sum = make_float3(0.0f, 0.0f, 0.0f);
}
}
/* Reject invalid value */
float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
if(!isfinite_safe(sum)) {
kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
L_sum = make_float3(0.0f, 0.0f, 0.0f);
/* Compute alpha. */
*alpha = 1.0f - L->transparent;
/* Add shadow catcher contributions. */
#ifdef __SHADOW_TRICKS__
if(L->has_shadow_catcher) {
path_radiance_sum_shadowcatcher(kg, L, &L_sum, alpha);
}
#endif /* __SHADOW_TRICKS__ */
return L_sum;
}
@ -627,14 +706,18 @@ ccl_device_inline void path_radiance_split_denoising(KernelGlobals *kg, PathRadi
*clean = make_float3(0.0f, 0.0f, 0.0f);
#endif
#ifdef __SHADOW_TRICKS__
if(L->has_shadow_catcher) {
*noisy += L->shadow_background_color;
}
#endif
*noisy = ensure_finite3(*noisy);
*clean = ensure_finite3(*clean);
}
ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample, int num_samples)
ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance *L_sample)
{
float fac = 1.0f/num_samples;
#ifdef __SPLIT_KERNEL__
# define safe_float3_add(f, v) \
do { \
@ -643,66 +726,35 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
atomic_add_and_fetch_float(p+1, (v).y); \
atomic_add_and_fetch_float(p+2, (v).z); \
} while(0)
# define safe_float_add(f, v) \
atomic_add_and_fetch_float(&(f), (v))
#else
# define safe_float3_add(f, v) (f) += (v)
# define safe_float_add(f, v) (f) += (v)
#endif /* __SPLIT_KERNEL__ */
#ifdef __PASSES__
safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse*fac);
safe_float3_add(L->direct_glossy, L_sample->direct_glossy*fac);
safe_float3_add(L->direct_transmission, L_sample->direct_transmission*fac);
safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface*fac);
safe_float3_add(L->direct_scatter, L_sample->direct_scatter*fac);
safe_float3_add(L->direct_diffuse, L_sample->direct_diffuse);
safe_float3_add(L->direct_glossy, L_sample->direct_glossy);
safe_float3_add(L->direct_transmission, L_sample->direct_transmission);
safe_float3_add(L->direct_subsurface, L_sample->direct_subsurface);
safe_float3_add(L->direct_scatter, L_sample->direct_scatter);
safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse*fac);
safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy*fac);
safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission*fac);
safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface*fac);
safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter*fac);
safe_float3_add(L->indirect_diffuse, L_sample->indirect_diffuse);
safe_float3_add(L->indirect_glossy, L_sample->indirect_glossy);
safe_float3_add(L->indirect_transmission, L_sample->indirect_transmission);
safe_float3_add(L->indirect_subsurface, L_sample->indirect_subsurface);
safe_float3_add(L->indirect_scatter, L_sample->indirect_scatter);
safe_float3_add(L->background, L_sample->background*fac);
safe_float3_add(L->ao, L_sample->ao*fac);
safe_float3_add(L->shadow, L_sample->shadow*fac);
# ifdef __SPLIT_KERNEL__
atomic_add_and_fetch_float(&L->mist, L_sample->mist*fac);
# else
L->mist += L_sample->mist*fac;
# endif /* __SPLIT_KERNEL__ */
safe_float3_add(L->background, L_sample->background);
safe_float3_add(L->ao, L_sample->ao);
safe_float3_add(L->shadow, L_sample->shadow);
safe_float_add(L->mist, L_sample->mist);
#endif /* __PASSES__ */
safe_float3_add(L->emission, L_sample->emission*fac);
safe_float3_add(L->emission, L_sample->emission);
#undef safe_float_add
#undef safe_float3_add
}
#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 L->shadow_transparency;
}
/* Calculate final light sum and transparency for shadow catcher object. */
ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg,
const PathRadiance *L,
float* alpha)
{
const float shadow = path_radiance_sum_shadow(L);
float3 L_sum;
if(kernel_data.background.transparent) {
*alpha = 1.0f - L->shadow_throughput * shadow;
L_sum = L->shadow_radiance_sum;
}
else {
L_sum = L->shadow_background_color * L->shadow_throughput * shadow +
L->shadow_radiance_sum;
}
return L_sum;
}
#endif
CCL_NAMESPACE_END

@ -70,7 +70,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* sample emission */
if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce);
path_radiance_accum_emission(&L_sample, &state, throughput, emission);
}
bool is_sss_sample = false;
@ -102,7 +102,6 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
&emission_sd,
&ray,
throughput,
state.num_samples,
&state,
&L_sample);
kernel_path_subsurface_accum_indirect(&ss_indirect, &L_sample);
@ -121,7 +120,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
state.ray_t = 0.0f;
#endif
/* compute indirect light */
kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, 1, &state, &L_sample);
kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
/* sum and reset indirect light pass variables for the next samples */
path_radiance_sum_indirect(&L_sample);
@ -141,7 +140,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* sample emission */
if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce);
path_radiance_accum_emission(&L_sample, &state, throughput, emission);
}
#ifdef __SUBSURFACE__
@ -172,7 +171,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
#endif
/* accumulate into master L */
path_radiance_accum_sample(L, &L_sample, 1);
path_radiance_accum_sample(L, &L_sample);
}
ccl_device bool is_aa_pass(ShaderEvalType type)
@ -368,7 +367,8 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
case SHADER_EVAL_COMBINED:
{
if((pass_filter & BAKE_FILTER_COMBINED) == BAKE_FILTER_COMBINED) {
out = path_radiance_clamp_and_sum(kg, &L);
float alpha;
out = path_radiance_clamp_and_sum(kg, &L, &alpha);
break;
}

@ -37,9 +37,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
ray.D = ls->D;
ray.P = ls->P;
ray.t = 1.0f;
# ifdef __OBJECT_MOTION__
ray.time = time;
# endif
ray.dP = differential3_zero();
ray.dD = dI;

@ -396,11 +396,13 @@ ccl_device_inline float3 background_light_sample(KernelGlobals *kg,
+ (1.0f - portal_sampling_pdf) * cdf_pdf);
}
return D;
} else {
}
else {
/* Sample map, but with nonzero portal_sampling_pdf for MIS. */
randu = (randu - portal_sampling_pdf) / (1.0f - portal_sampling_pdf);
}
} else {
}
else {
/* We can't sample a portal.
* Check if we can sample the map instead.
*/
@ -772,7 +774,8 @@ ccl_device_inline bool triangle_world_space_vertices(KernelGlobals *kg, int obje
if(object_flag & SD_OBJECT_HAS_VERTEX_MOTION && time >= 0.0f) {
motion_triangle_vertices(kg, object, prim, time, V);
has_motion = true;
} else {
}
else {
triangle_vertices(kg, prim, V);
}
@ -839,13 +842,15 @@ ccl_device_forceinline float triangle_light_pdf(KernelGlobals *kg, ShaderData *s
/* pdf_triangles is calculated over triangle area, but we're not sampling over its area */
if(UNLIKELY(solid_angle == 0.0f)) {
return 0.0f;
} else {
}
else {
float area = 1.0f;
if(has_motion) {
/* get the center frame vertices, this is what the PDF was calculated from */
triangle_world_space_vertices(kg, sd->object, sd->prim, -1.0f, V);
area = triangle_area(V[0], V[1], V[2]);
} else {
}
else {
area = 0.5f * len(N);
}
const float pdf = area * kernel_data.integrator.pdf_triangles;
@ -965,19 +970,25 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg, int prim, i
ls->D = z * B + safe_sqrtf(1.0f - z*z) * safe_normalize(C_ - dot(C_, B) * B);
/* calculate intersection with the planar triangle */
ray_triangle_intersect(P, ls->D, FLT_MAX,
if(!ray_triangle_intersect(P, ls->D, FLT_MAX,
#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
(ssef*)V,
(ssef*)V,
#else
V[0], V[1], V[2],
V[0], V[1], V[2],
#endif
&ls->u, &ls->v, &ls->t);
&ls->u, &ls->v, &ls->t)) {
ls->pdf = 0.0f;
return;
}
ls->P = P + ls->D * ls->t;
/* pdf_triangles is calculated over triangle area, but we're sampling over solid angle */
if(UNLIKELY(solid_angle == 0.0f)) {
ls->pdf = 0.0f;
} else {
return;
}
else {
if(has_motion) {
/* get the center frame vertices, this is what the PDF was calculated from */
triangle_world_space_vertices(kg, object, prim, -1.0f, V);
@ -1013,20 +1024,21 @@ ccl_device_forceinline void triangle_light_sample(KernelGlobals *kg, int prim, i
/* Light Distribution */
ccl_device int light_distribution_sample(KernelGlobals *kg, float randt)
ccl_device int light_distribution_sample(KernelGlobals *kg, float *randu)
{
/* this is basically std::upper_bound as used by pbrt, to find a point light or
/* This is basically std::upper_bound as used by pbrt, to find a point light or
* triangle to emit from, proportional to area. a good improvement would be to
* also sample proportional to power, though it's not so well defined with
* OSL shaders. */
* arbitrary shaders. */
int first = 0;
int len = kernel_data.integrator.num_distribution + 1;
float r = *randu;
while(len > 0) {
int half_len = len >> 1;
int middle = first + half_len;
if(randt < kernel_tex_fetch(__light_distribution, middle).x) {
if(r < kernel_tex_fetch(__light_distribution, middle).x) {
len = half_len;
}
else {
@ -1035,9 +1047,17 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt)
}
}
/* clamping should not be needed but float rounding errors seem to
* make this fail on rare occasions */
return clamp(first-1, 0, kernel_data.integrator.num_distribution-1);
/* Clamping should not be needed but float rounding errors seem to
* make this fail on rare occasions. */
int index = clamp(first-1, 0, kernel_data.integrator.num_distribution-1);
/* Rescale to reuse random number. this helps the 2D samples within
* each area light be stratified as well. */
float distr_min = kernel_tex_fetch(__light_distribution, index).x;
float distr_max = kernel_tex_fetch(__light_distribution, index+1).x;
*randu = (r - distr_min)/(distr_max - distr_min);
return index;
}
/* Generic Light */
@ -1049,7 +1069,6 @@ ccl_device bool light_select_reached_max_bounces(KernelGlobals *kg, int index, i
}
ccl_device_noinline bool light_sample(KernelGlobals *kg,
float randt,
float randu,
float randv,
float time,
@ -1058,7 +1077,7 @@ ccl_device_noinline bool light_sample(KernelGlobals *kg,
LightSample *ls)
{
/* sample index */
int index = light_distribution_sample(kg, randt);
int index = light_distribution_sample(kg, &randu);
/* fetch light data */
float4 l = kernel_tex_fetch(__light_distribution, index);

@ -225,7 +225,7 @@ ccl_device_inline void kernel_write_debug_passes(KernelGlobals *kg,
#endif /* __KERNEL_DEBUG__ */
ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L,
ShaderData *sd, int sample, ccl_addr_space PathState *state, float3 throughput)
ShaderData *sd, ccl_addr_space PathState *state, float3 throughput)
{
#ifdef __PASSES__
int path_flag = state->flag;
@ -243,6 +243,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
kernel_data.film.pass_alpha_threshold == 0.0f ||
average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold)
{
int sample = state->sample;
if(sample == 0) {
if(flag & PASS_DEPTH) {
@ -364,21 +365,11 @@ ccl_device_inline void kernel_write_light_passes(KernelGlobals *kg, ccl_global f
}
ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float *buffer,
int sample, PathRadiance *L, bool is_shadow_catcher)
int sample, PathRadiance *L)
{
if(L) {
float3 L_sum;
float alpha = 1.0f - L->transparent;
#ifdef __SHADOW_TRICKS__
if(is_shadow_catcher) {
L_sum = path_radiance_sum_shadowcatcher(kg, L, &alpha);
}
else
#endif /* __SHADOW_TRICKS__ */
{
L_sum = path_radiance_clamp_and_sum(kg, L);
}
float alpha;
float3 L_sum = path_radiance_clamp_and_sum(kg, L, &alpha);
kernel_write_pass_float4(buffer, sample, make_float4(L_sum.x, L_sum.y, L_sum.z, alpha));
@ -393,16 +384,7 @@ ccl_device_inline void kernel_write_result(KernelGlobals *kg, ccl_global float *
# endif
if(kernel_data.film.pass_denoising_clean) {
float3 noisy, clean;
#ifdef __SHADOW_TRICKS__
if(is_shadow_catcher) {
noisy = L_sum;
clean = make_float3(0.0f, 0.0f, 0.0f);
}
else
#endif /* __SHADOW_TRICKS__ */
{
path_radiance_split_denoising(kg, L, &noisy, &clean);
}
path_radiance_split_denoising(kg, L, &noisy, &clean);
kernel_write_pass_float3_variance(buffer + kernel_data.film.pass_denoising_data + DENOISING_PASS_COLOR,
sample, noisy);
kernel_write_pass_float3_unaligned(buffer + kernel_data.film.pass_denoising_clean,

File diff suppressed because it is too large Load Diff

@ -48,9 +48,7 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
light_ray.P = ray_offset(sd->P, sd->Ng);
light_ray.D = ao_D;
light_ray.t = kernel_data.background.ao_distance;
#ifdef __OBJECT_MOTION__
light_ray.time = sd->time;
#endif /* __OBJECT_MOTION__ */
light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
@ -144,7 +142,6 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
emission_sd,
&bsdf_ray,
tp*num_samples_inv,
num_samples,
&ps,
L);
@ -271,8 +268,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
int sample,
Ray ray,
ccl_global float *buffer,
PathRadiance *L,
bool *is_shadow_catcher)
PathRadiance *L)
{
/* initialize */
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
@ -292,36 +288,9 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
* Indirect bounces are handled in kernel_branched_path_surface_indirect_light().
*/
for(;;) {
/* intersect scene */
/* Find intersection with objects in scene. */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
#ifdef __HAIR__
float difl = 0.0f, extmax = 0.0f;
uint lcg_state = 0;
if(kernel_data.bvh.have_curves) {
if(kernel_data.cam.resolution == 1) {
float3 pixdiff = ray.dD.dx + ray.dD.dy;
/*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
}
extmax = kernel_data.curve.maximum_width;
lcg_state = lcg_state_init(&state, 0x51633e2d);
}
bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
#else
bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f);
#endif /* __HAIR__ */
#ifdef __KERNEL_DEBUG__
L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
L->debug_data.num_bvh_intersections += isect.num_intersections;
L->debug_data.num_ray_bounces++;
#endif /* __KERNEL_DEBUG__ */
bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L);
#ifdef __VOLUME__
/* Sanitize volume stack. */
@ -376,10 +345,8 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
&ps, &pray, &sd, &tp, rphase, rscatter, &volume_segment, NULL, false);
(void)result;
kernel_assert(result == VOLUME_PATH_SCATTERED);
if(kernel_path_volume_bounce(kg,
if(result == VOLUME_PATH_SCATTERED &&
kernel_path_volume_bounce(kg,
&sd,
&tp,
&ps,
@ -391,7 +358,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
&emission_sd,
&pray,
tp*num_samples_inv,
num_samples,
&ps,
L);
@ -405,7 +371,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
/* emission and transmittance */
if(volume_segment.closure_flag & SD_EMISSION)
path_radiance_accum_emission(L, throughput, volume_segment.accum_emission, state.bounce);
path_radiance_accum_emission(L, &state, throughput, volume_segment.accum_emission);
throughput *= volume_segment.accum_transmittance;
/* free cached steps */
@ -447,7 +413,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
&emission_sd,
&pray,
tp,
num_samples,
&ps,
L);
@ -466,79 +431,29 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
}
#endif /* __VOLUME__ */
/* Shade background. */
if(!hit) {
/* eval background shader if nothing hit */
if(kernel_data.background.transparent) {
L->transparent += average(throughput);
#ifdef __PASSES__
if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
#endif /* __PASSES__ */
break;
}
#ifdef __BACKGROUND__
/* sample background shader */
float3 L_background = indirect_background(kg, &emission_sd, &state, &ray);
path_radiance_accum_background(L, &state, throughput, L_background);
#endif /* __BACKGROUND__ */
kernel_path_background(kg, &state, &ray, throughput, &emission_sd, L);
break;
}
/* setup shading */
/* Setup and evaluate shader. */
shader_setup_from_ray(kg, &sd, &isect, &ray);
shader_eval_surface(kg, &sd, &state, 0.0f, state.flag);
shader_merge_closures(&sd);
#ifdef __SHADOW_TRICKS__
if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
state.flag |= (PATH_RAY_SHADOW_CATCHER |
PATH_RAY_STORE_SHADOW_INFO);
if(!kernel_data.background.transparent) {
L->shadow_background_color =
indirect_background(kg, &emission_sd, &state, &ray);
}
L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
L->shadow_throughput = average(throughput);
/* Apply shadow catcher, holdout, emission. */
if(!kernel_path_shader_apply(kg,
&sd,
&state,
&ray,
throughput,
&emission_sd,
L,
buffer))
{
break;
}
else if(state.flag & PATH_RAY_SHADOW_CATCHER) {
/* Only update transparency after shadow catcher bounce. */
L->shadow_transparency *=
average(shader_bsdf_transparency(kg, &sd));
}
#endif /* __SHADOW_TRICKS__ */
/* holdout */
#ifdef __HOLDOUT__
if((sd.flag & SD_HOLDOUT) || (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) {
if(kernel_data.background.transparent) {
float3 holdout_weight;
if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
}
else {
holdout_weight = shader_holdout_eval(kg, &sd);
}
/* any throughput is ok, should all be identical here */
L->transparent += average(holdout_weight*throughput);
}
if(sd.object_flag & SD_OBJECT_HOLDOUT_MASK) {
break;
}
}
#endif /* __HOLDOUT__ */
/* holdout mask objects do not write data passes */
kernel_write_data_passes(kg, buffer, L, &sd, sample, &state, throughput);
#ifdef __EMISSION__
/* emission */
if(sd.flag & SD_EMISSION) {
float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf);
path_radiance_accum_emission(L, throughput, emission, state.bounce);
}
#endif /* __EMISSION__ */
/* transparency termination */
if(state.flag & PATH_RAY_TRANSPARENT) {
@ -620,10 +535,6 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
kernel_volume_stack_enter_exit(kg, &sd, state.volume_stack);
#endif /* __VOLUME__ */
}
#ifdef __SHADOW_TRICKS__
*is_shadow_catcher = (state.flag & PATH_RAY_SHADOW_CATCHER) != 0;
#endif /* __SHADOW_TRICKS__ */
}
ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
@ -645,14 +556,13 @@ ccl_device void kernel_branched_path_trace(KernelGlobals *kg,
/* integrate */
PathRadiance L;
bool is_shadow_catcher;
if(ray.t != 0.0f) {
kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L, &is_shadow_catcher);
kernel_write_result(kg, buffer, sample, &L, is_shadow_catcher);
kernel_branched_path_integrate(kg, rng_hash, sample, ray, buffer, &L);
kernel_write_result(kg, buffer, sample, &L);
}
else {
kernel_write_result(kg, buffer, sample, NULL, false);
kernel_write_result(kg, buffer, sample, NULL);
}
}

@ -29,6 +29,7 @@ ccl_device_inline void path_state_init(KernelGlobals *kg,
state->rng_offset = PRNG_BASE_NUM;
state->sample = sample;
state->num_samples = kernel_data.integrator.aa_samples;
state->branch_factor = 1.0f;
state->bounce = 0;
state->diffuse_bounce = 0;
@ -143,7 +144,7 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
#endif
}
ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state)
ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, ccl_addr_space PathState *state)
{
uint flag = state->flag & PATH_RAY_ALL_VISIBILITY;
@ -157,7 +158,9 @@ ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *s
return flag;
}
ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg, ccl_addr_space PathState *state, const float3 throughput)
ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg,
ccl_addr_space PathState *state,
const float3 throughput)
{
if(state->flag & PATH_RAY_TRANSPARENT) {
/* Transparent rays are treated separately with own max bounces. */
@ -201,7 +204,7 @@ ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg, c
/* Probalistic termination: use sqrt() to roughly match typical view
* transform and do path termination a bit later on average. */
return sqrtf(max3(fabs(throughput)));
return min(sqrtf(max3(fabs(throughput)) * state->branch_factor), 1.0f);
}
/* TODO(DingTo): Find more meaningful name for this */
@ -214,5 +217,30 @@ ccl_device_inline void path_state_modify_bounce(ccl_addr_space PathState *state,
state->bounce -= 1;
}
ccl_device_inline bool path_state_ao_bounce(KernelGlobals *kg, ccl_addr_space PathState *state)
{
if(state->bounce <= kernel_data.integrator.ao_bounces) {
return false;
}
int bounce = state->bounce - state->transmission_bounce - (state->glossy_bounce > 0);
return (bounce > kernel_data.integrator.ao_bounces);
}
ccl_device_inline void path_state_branch(ccl_addr_space PathState *state,
int branch,
int num_branches)
{
state->rng_offset += PRNG_BOUNCE_NUM;
if(num_branches > 1) {
/* Path is splitting into a branch, adjust so that each branch
* still gets a unique sample from the same sequence. */
state->sample = state->sample*num_branches + branch;
state->num_samples = state->num_samples*num_branches;
state->branch_factor *= num_branches;
}
}
CCL_NAMESPACE_END

@ -124,7 +124,7 @@ bool kernel_path_subsurface_scatter(
ss_indirect->num_rays++;
}
else {
path_radiance_accum_sample(L, hit_L, 1);
path_radiance_accum_sample(L, hit_L);
}
}
return true;
@ -145,7 +145,7 @@ ccl_device void kernel_path_subsurface_accum_indirect(
{
if(ss_indirect->tracing) {
path_radiance_sum_indirect(L);
path_radiance_accum_sample(&ss_indirect->direct_L, L, 1);
path_radiance_accum_sample(&ss_indirect->direct_L, L);
if(ss_indirect->num_rays == 0) {
*L = ss_indirect->direct_L;
}

@ -85,17 +85,16 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
float num_samples_inv = num_samples_adjust/num_samples;
for(int j = 0; j < num_samples; j++) {
float light_t = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT);
float light_u, light_v;
path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
float terminate = path_branched_rng_light_termination(kg, state->rng_hash, state, j, num_samples);
/* only sample triangle lights */
if(kernel_data.integrator.num_all_lights)
light_t = 0.5f*light_t;
light_u = 0.5f*light_u;
LightSample ls;
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
/* Same as above, probability needs to be corrected since the sampling was forced to select a mesh light. */
if(kernel_data.integrator.num_all_lights)
ls.pdf *= 2.0f;
@ -118,13 +117,12 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(
}
else {
/* sample one light at random */
float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
float terminate = path_state_rng_light_termination(kg, state);
LightSample ls;
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
/* sample random light */
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
@ -238,7 +236,6 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg,
#endif
/* sample illumination from lights to find path contribution */
float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
@ -251,7 +248,7 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg,
#endif
LightSample ls;
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
float terminate = path_state_rng_light_termination(kg, state);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */

@ -31,7 +31,6 @@ ccl_device_inline void kernel_path_volume_connect_light(
return;
/* sample illumination from lights to find path contribution */
float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
@ -41,11 +40,9 @@ ccl_device_inline void kernel_path_volume_connect_light(
bool is_lamp;
/* connect to light from given point where shader has been evaluated */
# ifdef __OBJECT_MOTION__
light_ray.time = sd->time;
# endif
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls))
if(light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls))
{
float terminate = path_state_rng_light_termination(kg, state);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
@ -135,9 +132,7 @@ ccl_device void kernel_branched_path_volume_connect_light(
BsdfEval L_light;
bool is_lamp;
# ifdef __OBJECT_MOTION__
light_ray.time = sd->time;
# endif
if(sample_all_lights) {
/* lamp sampling */
@ -166,11 +161,9 @@ ccl_device void kernel_branched_path_volume_connect_light(
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
(void)result;
kernel_assert(result == VOLUME_PATH_SCATTERED);
/* todo: split up light_sample so we don't have to call it again with new position */
if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
if(result == VOLUME_PATH_SCATTERED &&
lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
if(kernel_data.integrator.pdf_triangles != 0.0f)
ls.pdf *= 2.0f;
@ -195,16 +188,15 @@ ccl_device void kernel_branched_path_volume_connect_light(
for(int j = 0; j < num_samples; j++) {
/* sample random position on random triangle */
float light_t = path_branched_rng_1D_for_decision(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT);
float light_u, light_v;
path_branched_rng_2D(kg, state->rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
/* only sample triangle lights */
if(kernel_data.integrator.num_all_lights)
light_t = 0.5f*light_t;
light_u = 0.5f*light_u;
LightSample ls;
light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
float3 tp = throughput;
@ -215,11 +207,9 @@ ccl_device void kernel_branched_path_volume_connect_light(
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
(void)result;
kernel_assert(result == VOLUME_PATH_SCATTERED);
/* todo: split up light_sample so we don't have to call it again with new position */
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
if(result == VOLUME_PATH_SCATTERED &&
light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
if(kernel_data.integrator.num_all_lights)
ls.pdf *= 2.0f;
@ -239,12 +229,11 @@ ccl_device void kernel_branched_path_volume_connect_light(
}
else {
/* sample random position on random light */
float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
LightSample ls;
light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
light_sample(kg, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
float3 tp = throughput;
@ -255,11 +244,9 @@ ccl_device void kernel_branched_path_volume_connect_light(
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
(void)result;
kernel_assert(result == VOLUME_PATH_SCATTERED);
/* todo: split up light_sample so we don't have to call it again with new position */
if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
if(result == VOLUME_PATH_SCATTERED &&
light_sample(kg, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
/* sample random light */
float terminate = path_state_rng_light_termination(kg, state);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {

@ -296,17 +296,6 @@ ccl_device_inline float path_branched_rng_light_termination(
return 0.0f;
}
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 */
state->rng_offset += PRNG_BOUNCE_NUM;
state->sample = state->sample*num_branches + branch;
state->num_samples = state->num_samples*num_branches;
}
ccl_device_inline uint lcg_state_init(PathState *state,
uint scramble)
{

@ -66,8 +66,8 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
/* matrices and time */
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, ray->time);
sd->time = ray->time;
#endif
sd->time = ray->time;
sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
sd->ray_length = isect->t;
@ -271,17 +271,17 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
sd->u = u;
sd->v = v;
#endif
sd->time = time;
sd->ray_length = t;
sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
sd->object_flag = 0;
if(sd->object != OBJECT_NONE) {
sd->object_flag |= kernel_tex_fetch(__object_flag,
sd->object);
sd->object);
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, time);
sd->time = time;
}
else if(lamp != LAMP_NONE) {
sd->ob_tfm = lamp_fetch_transform(kg, lamp, false);
@ -385,9 +385,7 @@ ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderDat
sd->shader = kernel_data.background.surface_shader;
sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
sd->object_flag = 0;
#ifdef __OBJECT_MOTION__
sd->time = ray->time;
#endif
sd->ray_length = 0.0f;
#ifdef __INSTANCING__
@ -427,9 +425,7 @@ ccl_device_inline void shader_setup_from_volume(KernelGlobals *kg, ShaderData *s
sd->shader = SHADER_NONE;
sd->flag = 0;
sd->object_flag = 0;
#ifdef __OBJECT_MOTION__
sd->time = ray->time;
#endif
sd->ray_length = 0.0f; /* todo: can we set this to some useful value? */
#ifdef __INSTANCING__

@ -16,6 +16,39 @@
CCL_NAMESPACE_BEGIN
#ifdef __VOLUME__
typedef struct VolumeState {
# ifdef __SPLIT_KERNEL__
# else
PathState ps;
# endif
} VolumeState;
/* Get PathState ready for use for volume stack evaluation. */
ccl_device_inline PathState *shadow_blocked_volume_path_state(
KernelGlobals *kg,
VolumeState *volume_state,
ccl_addr_space PathState *state,
ShaderData *sd,
Ray *ray)
{
# ifdef __SPLIT_KERNEL__
ccl_addr_space PathState *ps =
&kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
# else
PathState *ps = &volume_state->ps;
# endif
*ps = *state;
/* We are checking for shadow on the "other" side of the surface, so need
* to discard volume we are currently at.
*/
if(dot(sd->Ng, ray->D) < 0.0f) {
kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack);
}
return ps;
}
#endif /* __VOLUME__ */
/* Attenuate throughput accordingly to the given intersection event.
* Returns true if the throughput is zero and traversal can be aborted.
*/
@ -119,39 +152,6 @@ ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
# define SHADOW_STACK_MAX_HITS 64
# ifdef __VOLUME__
struct VolumeState {
# ifdef __SPLIT_KERNEL__
# else
PathState ps;
# endif
};
/* Get PathState ready for use for volume stack evaluation. */
ccl_device_inline PathState *shadow_blocked_volume_path_state(
KernelGlobals *kg,
VolumeState *volume_state,
ccl_addr_space PathState *state,
ShaderData *sd,
Ray *ray)
{
# ifdef __SPLIT_KERNEL__
ccl_addr_space PathState *ps =
&kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
# else
PathState *ps = &volume_state->ps;
# endif
*ps = *state;
/* We are checking for shadow on the "other" side of the surface, so need
* to discard volume we are currently at.
*/
if(dot(sd->Ng, ray->D) < 0.0f) {
kernel_volume_stack_enter_exit(kg, sd, ps->volume_stack);
}
return ps;
}
#endif // __VOLUME__
/* Actual logic with traversal loop implementation which is free from device
* specific tweaks.
*

@ -292,7 +292,7 @@ enum PathTraceDimension {
PRNG_BSDF_U = 0,
PRNG_BSDF_V = 1,
PRNG_BSDF = 2,
PRNG_LIGHT = 3,
PRNG_UNUSED3 = 3,
PRNG_LIGHT_U = 4,
PRNG_LIGHT_V = 5,
PRNG_LIGHT_TERMINATE = 6,
@ -535,11 +535,13 @@ typedef ccl_addr_space struct PathRadiance {
/* Path radiance sum and throughput at the moment when ray hits shadow
* catcher object.
*/
float3 shadow_radiance_sum;
float shadow_throughput;
/* Accumulated transparency along the path after shadow catcher bounce. */
float shadow_transparency;
/* Indicate if any shadow catcher data is set. */
int has_shadow_catcher;
#endif
#ifdef __DENOISING_FEATURES__
@ -1006,9 +1008,10 @@ typedef struct PathState {
/* random number generator state */
uint rng_hash; /* per pixel hash */
int rng_offset; /* dimension offset */
int sample; /* path sample number */
int num_samples; /* total number of times this path will be sampled */
int rng_offset; /* dimension offset */
int sample; /* path sample number */
int num_samples; /* total number of times this path will be sampled */
float branch_factor; /* number of branches in indirect paths */
/* bounce counting */
int bounce;

@ -438,7 +438,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
float3 sigma_t = coeff.sigma_a + coeff.sigma_s;
float3 transmittance = volume_color_transmittance(sigma_t, ray->t);
float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, ray->t);
path_radiance_accum_emission(L, *throughput, emission, state->bounce);
path_radiance_accum_emission(L, state, *throughput, emission);
}
/* modify throughput */
@ -558,7 +558,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
/* integrate emission attenuated by absorption */
if(L && (closure_flag & SD_EMISSION)) {
float3 emission = kernel_volume_emission_integrate(&coeff, closure_flag, transmittance, dt);
path_radiance_accum_emission(L, tp, emission, state->bounce);
path_radiance_accum_emission(L, state, tp, emission);
}
/* modify throughput */
@ -997,8 +997,8 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
mis_weight = 2.0f*power_heuristic(pdf, distance_pdf);
}
}
if(sample_t < 1e-6f || pdf == 0.0f) {
return VOLUME_PATH_SCATTERED;
if(sample_t < 0.0f || pdf == 0.0f) {
return VOLUME_PATH_MISSED;
}
/* compute transmittance up to this step */

@ -188,7 +188,6 @@ ccl_device_noinline bool kernel_split_branched_path_surface_indirect_light_iter(
/* update state for next iteration */
branched_state->next_closure = i;
branched_state->next_sample = j+1;
branched_state->num_samples = num_samples;
/* start the indirect path */
*tp *= num_samples_inv;

@ -94,8 +94,7 @@ ccl_device void kernel_buffer_update(KernelGlobals *kg,
buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
/* accumulate result in output buffer */
bool is_shadow_catcher = (state->flag & PATH_RAY_SHADOW_CATCHER);
kernel_write_result(kg, buffer, sample, L, is_shadow_catcher);
kernel_write_result(kg, buffer, sample, L);
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
}

@ -81,23 +81,20 @@ ccl_device void kernel_direct_lighting(KernelGlobals *kg,
if(flag) {
/* Sample illumination from lights to find path contribution. */
float light_t = path_state_rng_1D(kg, state, PRNG_LIGHT);
float light_u, light_v;
path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
float terminate = path_state_rng_light_termination(kg, state);
LightSample ls;
if(light_sample(kg,
light_t, light_u, light_v,
light_u, light_v,
sd->time,
sd->P,
state->bounce,
&ls)) {
Ray light_ray;
# ifdef __OBJECT_MOTION__
light_ray.time = sd->time;
# endif
BsdfEval L_light;
bool is_lamp;

@ -72,7 +72,6 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K
/* start the indirect path */
branched_state->next_closure = 0;
branched_state->next_sample = j+1;
branched_state->num_samples = num_samples;
/* Attempting to share too many samples is slow for volumes as it causes us to
* loop here more and have many calls to kernel_volume_integrate which evaluates

@ -94,161 +94,63 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
ccl_global PathState *state = 0x0;
float3 throughput;
uint sample;
ccl_global char *ray_state = kernel_split_state.ray_state;
ShaderData *sd = &kernel_split_state.sd[ray_index];
ccl_global float *buffer = kernel_split_params.buffer;
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
uint work_index = kernel_split_state.work_array[ray_index];
sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
uint pixel_x, pixel_y, tile_x, tile_y;
get_work_pixel_tile_position(kg, &pixel_x, &pixel_y,
&tile_x, &tile_y,
work_index,
ray_index);
ccl_global float *buffer = kernel_split_params.buffer;
buffer += (kernel_split_params.offset + pixel_x + pixel_y * stride) * kernel_data.film.pass_stride;
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
throughput = kernel_split_state.throughput[ray_index];
state = &kernel_split_state.path_state[ray_index];
#ifdef __SHADOW_TRICKS__
if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
if(state->flag & PATH_RAY_CAMERA) {
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
state->flag |= (PATH_RAY_SHADOW_CATCHER |
PATH_RAY_STORE_SHADOW_INFO);
if(!kernel_data.background.transparent) {
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
L->shadow_background_color = indirect_background(
kg,
&kernel_split_state.sd_DL_shadow[ray_index],
state,
ray);
}
L->shadow_radiance_sum = path_radiance_clamp_and_sum(kg, L);
L->shadow_throughput = average(throughput);
}
}
else if(state->flag & PATH_RAY_SHADOW_CATCHER) {
/* Only update transparency after shadow catcher bounce. */
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
L->shadow_transparency *= average(shader_bsdf_transparency(kg, sd));
}
#endif /* __SHADOW_TRICKS__ */
/* holdout */
#ifdef __HOLDOUT__
if(((sd->flag & SD_HOLDOUT) ||
(sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
(state->flag & PATH_RAY_CAMERA))
if(!kernel_path_shader_apply(kg,
sd,
state,
ray,
throughput,
emission_sd,
L,
buffer))
{
if(kernel_data.background.transparent) {
float3 holdout_weight;
if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
}
else {
holdout_weight = shader_holdout_eval(kg, sd);
}
/* any throughput is ok, should all be identical here */
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
L->transparent += average(holdout_weight*throughput);
}
if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
kernel_split_path_end(kg, ray_index);
}
kernel_split_path_end(kg, ray_index);
}
#endif /* __HOLDOUT__ */
}
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
#ifdef __BRANCHED_PATH__
if(!IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT))
#endif /* __BRANCHED_PATH__ */
{
/* Holdout mask objects do not write data passes. */
kernel_write_data_passes(kg,
buffer,
L,
sd,
sample,
state,
throughput);
}
/* Blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy.
*/
#ifndef __BRANCHED_PATH__
if(kernel_data.integrator.filter_glossy != FLT_MAX)
#else
if(kernel_data.integrator.filter_glossy != FLT_MAX &&
(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)))
#endif /* __BRANCHED_PATH__ */
{
float blur_pdf = kernel_data.integrator.filter_glossy*state->min_ray_pdf;
if(blur_pdf < 1.0f) {
float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
shader_bsdf_blur(kg, sd, blur_roughness);
}
}
#ifdef __EMISSION__
/* emission */
if(sd->flag & SD_EMISSION) {
/* TODO(sergey): is isect.t wrong here for transparent surfaces? */
float3 emission = indirect_primitive_emission(
kg,
sd,
kernel_split_state.isect[ray_index].t,
state->flag,
state->ray_pdf);
path_radiance_accum_emission(L, throughput, emission, state->bounce);
}
#endif /* __EMISSION__ */
/* Path termination. this is a strange place to put the termination, it's
* mainly due to the mixed in MIS that we use. gives too many unneeded
* shader evaluations, only need emission if we are going to terminate.
*/
#ifndef __BRANCHED_PATH__
float probability = path_state_continuation_probability(kg, state, throughput);
#else
float probability = 1.0f;
if(!kernel_data.integrator.branched) {
probability = path_state_continuation_probability(kg, state, throughput);
}
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
int num_samples = kernel_split_state.branched_state[ray_index].num_samples;
probability = path_state_continuation_probability(kg, state, throughput*num_samples);
}
else if(state->flag & PATH_RAY_TRANSPARENT) {
probability = path_state_continuation_probability(kg, state, throughput);
}
#endif
if(probability == 0.0f) {
kernel_split_path_end(kg, ray_index);
}
else if(probability < 1.0f) {
float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE);
if(terminate >= probability) {
kernel_split_path_end(kg, ray_index);
}
else {
kernel_split_state.throughput[ray_index] = throughput/probability;
}
}
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
if(probability != 1.0f) {
float terminate = path_state_rng_1D_for_decision(kg, state, PRNG_TERMINATE);
if(terminate >= probability) {
kernel_split_path_end(kg, ray_index);
}
else {
kernel_split_state.throughput[ray_index] = throughput/probability;
}
}
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
kernel_update_denoising_features(kg, sd, state, L);
}
}

@ -33,7 +33,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
if(ray_index != QUEUE_EMPTY_SLOT) {
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
if(state->bounce > kernel_data.integrator.ao_bounces) {
if(path_state_ao_bounce(kg, state)) {
kernel_split_path_end(kg, ray_index);
}
}
@ -50,32 +50,16 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
return;
}
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
/* eval background shader if nothing hit */
if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) {
L->transparent += average((*throughput));
#ifdef __PASSES__
if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
#endif
kernel_split_path_end(kg, ray_index);
}
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
float3 throughput = kernel_split_state.throughput[ray_index];
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
#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, state, (*throughput), L_background);
#endif
kernel_split_path_end(kg, ray_index);
}
kernel_path_background(kg, state, ray, throughput, emission_sd, L);
kernel_split_path_end(kg, ray_index);
}
}
CCL_NAMESPACE_END

@ -57,27 +57,10 @@ ccl_device void kernel_lamp_emission(KernelGlobals *kg)
float3 throughput = kernel_split_state.throughput[ray_index];
Ray ray = kernel_split_state.ray[ray_index];
ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
#ifdef __LAMP_MIS__
if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) {
/* ray starting from previous non-transparent bounce */
Ray light_ray;
light_ray.P = ray.P - state->ray_t*ray.D;
state->ray_t += kernel_split_state.isect[ray_index].t;
light_ray.D = ray.D;
light_ray.t = state->ray_t;
light_ray.time = ray.time;
light_ray.dD = ray.dD;
light_ray.dP = ray.dP;
/* intersect with lamp */
float3 emission;
if(indirect_lamp_emission(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &light_ray, &emission)) {
path_radiance_accum_emission(L, throughput, emission, state->bounce);
}
}
#endif /* __LAMP_MIS__ */
kernel_path_lamp_emission(kg, state, &ray, throughput, isect, emission_sd, L);
}
}

@ -59,49 +59,13 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
return;
}
Intersection isect;
PathState state = kernel_split_state.path_state[ray_index];
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
Ray ray = kernel_split_state.ray[ray_index];
/* intersect scene */
uint visibility = path_state_ray_visibility(kg, &state);
if(state.bounce > kernel_data.integrator.ao_bounces) {
visibility = PATH_RAY_SHADOW;
ray.t = kernel_data.background.ao_distance;
}
#ifdef __HAIR__
float difl = 0.0f, extmax = 0.0f;
uint lcg_state = 0;
if(kernel_data.bvh.have_curves) {
if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
float3 pixdiff = ray.dD.dx + ray.dD.dy;
/*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
}
extmax = kernel_data.curve.maximum_width;
lcg_state = lcg_state_init(&state, 0x51633e2d);
}
bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
#else
bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f);
#endif
kernel_split_state.isect[ray_index] = isect;
#ifdef __KERNEL_DEBUG__
PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
if(state.flag & PATH_RAY_CAMERA) {
L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
L->debug_data.num_bvh_intersections += isect.num_intersections;
}
L->debug_data.num_ray_bounces++;
#endif
Intersection isect;
bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L);
kernel_split_state.isect[ray_index] = isect;
if(!hit) {
/* Change the state of rays that hit the background;

@ -63,7 +63,7 @@ ccl_device_inline void kernel_split_path_end(KernelGlobals *kg, int ray_index)
PathRadiance *orig_ray_L = &kernel_split_state.path_radiance[orig_ray];
path_radiance_sum_indirect(L);
path_radiance_accum_sample(orig_ray_L, L, 1);
path_radiance_accum_sample(orig_ray_L, L);
atomic_fetch_and_dec_uint32((ccl_global uint*)&kernel_split_state.branched_state[orig_ray].shared_sample_count);

@ -72,7 +72,6 @@ typedef ccl_global struct SplitBranchedState {
/* indirect loop state */
int next_closure;
int next_sample;
int num_samples;
#ifdef __SUBSURFACE__
int ss_next_closure;

@ -131,6 +131,11 @@ def align_objects(context,
cursor = (space if space and space.type == 'VIEW_3D' else scene).cursor_location
# We are accessing runtime data such as evaluated bounding box, so we need to
# be sure it is properly updated and valid (bounding box might be lost on operator
# redo).
scene.update()
Left_Front_Up_SEL = [0.0, 0.0, 0.0]
Right_Back_Down_SEL = [0.0, 0.0, 0.0]

@ -1135,9 +1135,13 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
if (fcu->totvert) {
float nmin, nmax;
/* get extents for this curve */
/* TODO: allow enabling/disabling this? */
calc_fcurve_range(fcu, &nmin, &nmax, false, true);
/* get extents for this curve
* - no "selected only", since this is often used in the backend
* - no "minimum length" (we will apply this later), otherwise
* single-keyframe curves will increase the overall length by
* a phantom frame (T50354)
*/
calc_fcurve_range(fcu, &nmin, &nmax, false, false);
/* compare to the running tally */
min = min_ff(min, nmin);
@ -1190,7 +1194,9 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
}
if (foundvert || foundmod) {
/* ensure that action is at least 1 frame long (for NLA strips to have a valid length) */
if (min == max) max += 1.0f;
*start = min;
*end = max;
}

@ -1092,13 +1092,10 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part
* distribution (see T47983 and its two example files). It allows us to consider pos as
* 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not),
* and avoid stumbling over float imprecisions in element_sum. */
if (from == PART_FROM_VERT) {
pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */
}
else {
pos = 0.0;
}
* and avoid stumbling over float imprecisions in element_sum.
* Note: moved face and volume distribution to this as well (instead of starting at zero),
* for the same reasons, see T52682. */
pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */
for (i = 0, p = 0; p < totpart; p++, pos += step) {
for ( ; (i < totmapped - 1) && (pos > (double)element_sum[i]); i++);
@ -1137,7 +1134,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
if (jitlevel == 0) {
jitlevel= totpart/totelem;
if (part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */
if (part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scientific */
if (jitlevel<3) jitlevel= 3;
}

@ -64,9 +64,21 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende
/* Make sure node tree has previews.
* Don't create previews in advance, this is done when adding preview operations.
* Reserved preview size is determined by render output for now.
*
* We fit the aspect into COM_PREVIEW_SIZE x COM_PREVIEW_SIZE image to avoid
* insane preview resolution, which might even overflow preview dimensions.
*/
float aspect = rd->xsch > 0 ? (float)rd->ysch / (float)rd->xsch : 1.0f;
BKE_node_preview_init_tree(editingtree, COM_PREVIEW_SIZE, (int)(COM_PREVIEW_SIZE * aspect), false);
const float aspect = rd->xsch > 0 ? (float)rd->ysch / (float)rd->xsch : 1.0f;
int preview_width, preview_height;
if (aspect < 1.0f) {
preview_width = COM_PREVIEW_SIZE;
preview_height = (int)(COM_PREVIEW_SIZE * aspect);
}
else {
preview_width = (int)(COM_PREVIEW_SIZE / aspect);
preview_height = COM_PREVIEW_SIZE;
}
BKE_node_preview_init_tree(editingtree, preview_width, preview_height, false);
/* initialize workscheduler, will check if already done. TODO deinitialize somewhere */
bool use_opencl = (editingtree->flag & NTREE_COM_OPENCL) != 0;

@ -15,8 +15,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor:
* Jeroen Bakker
* Contributor:
* Jeroen Bakker
* Monique Dewanchand
*/
@ -25,16 +25,22 @@
#include "COM_TranslateOperation.h"
#include "COM_RotateOperation.h"
#include "COM_ScaleOperation.h"
#include "COM_SetColorOperation.h"
#include "COM_SetValueOperation.h"
#include "COM_SetVectorOperation.h"
RenderLayersNode::RenderLayersNode(bNode *editorNode) : Node(editorNode)
{
/* pass */
}
void RenderLayersNode::testSocketLink(NodeConverter &converter, const CompositorContext &context,
NodeOutput *output, RenderLayersProg *operation,
Scene *scene, int layerId, bool is_preview) const
void RenderLayersNode::testSocketLink(NodeConverter &converter,
const CompositorContext &context,
NodeOutput *output,
RenderLayersProg *operation,
Scene *scene,
int layerId,
bool is_preview) const
{
operation->setScene(scene);
operation->setLayerId(layerId);
@ -43,45 +49,140 @@ void RenderLayersNode::testSocketLink(NodeConverter &converter, const Compositor
converter.mapOutputSocket(output, operation->getOutputSocket());
converter.addOperation(operation);
if (is_preview) /* only for image socket */
converter.addPreview(operation->getOutputSocket());
}
void RenderLayersNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
void RenderLayersNode::testRenderLink(NodeConverter &converter,
const CompositorContext &context,
Render *re) const
{
Scene *scene = (Scene *)this->getbNode()->id;
short layerId = this->getbNode()->custom1;
Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
int numberOfOutputs = this->getNumberOfOutputSockets();
if (re) {
RenderResult *rr = RE_AcquireResultRead(re);
if (rr) {
SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, layerId);
if (srl) {
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
if (rl) {
for (int i = 0; i < numberOfOutputs; i++) {
NodeOutput *output = this->getOutputSocket(i);
NodeImageLayer *storage = (NodeImageLayer*) output->getbNodeSocket()->storage;
RenderPass *rpass = (RenderPass*) BLI_findstring(&rl->passes, storage->pass_name, offsetof(RenderPass, name));
if (rpass) {
if (STREQ(rpass->name, RE_PASSNAME_COMBINED) && STREQ(output->getbNodeSocket()->name, "Alpha")) {
testSocketLink(converter, context, output, new RenderLayersAlphaProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false);
}
else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
testSocketLink(converter, context, output, new RenderLayersDepthProg(rpass->name, COM_DT_VALUE, rpass->channels), scene, layerId, false);
}
else {
DataType type = ((rpass->channels == 4)? COM_DT_COLOR : ((rpass->channels == 3)? COM_DT_VECTOR : COM_DT_VALUE));
testSocketLink(converter, context, output, new RenderLayersProg(rpass->name, type, rpass->channels), scene, layerId, STREQ(output->getbNodeSocket()->name, "Image"));
}
}
}
}
}
const short layerId = this->getbNode()->custom1;
RenderResult *rr = RE_AcquireResultRead(re);
if (rr == NULL) {
missingRenderLink(converter);
return;
}
SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, layerId);
if (srl == NULL) {
missingRenderLink(converter);
return;
}
RenderLayer *rl = RE_GetRenderLayer(rr, srl->name);
if (rl == NULL) {
missingRenderLink(converter);
return;
}
const int num_outputs = this->getNumberOfOutputSockets();
for (int i = 0; i < num_outputs; i++) {
NodeOutput *output = this->getOutputSocket(i);
NodeImageLayer *storage = (NodeImageLayer*) output->getbNodeSocket()->storage;
RenderPass *rpass = (RenderPass*) BLI_findstring(
&rl->passes,
storage->pass_name,
offsetof(RenderPass, name));
if (rpass == NULL) {
missingSocketLink(converter, output);
continue;
}
RE_ReleaseResult(re);
RenderLayersProg *operation;
bool is_preview;
if (STREQ(rpass->name, RE_PASSNAME_COMBINED) &&
STREQ(output->getbNodeSocket()->name, "Alpha"))
{
operation = new RenderLayersAlphaProg(rpass->name,
COM_DT_VALUE,
rpass->channels);
is_preview = false;
}
else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
operation = new RenderLayersDepthProg(rpass->name,
COM_DT_VALUE,
rpass->channels);
is_preview = false;
}
else {
DataType type;
switch (rpass->channels) {
case 4: type = COM_DT_COLOR; break;
case 3: type = COM_DT_VECTOR; break;
case 1: type = COM_DT_VALUE; break;
default:
BLI_assert(!"Unexpected number of channels for pass");
type = COM_DT_VALUE;
break;
}
operation = new RenderLayersProg(rpass->name,
type,
rpass->channels);
is_preview = STREQ(output->getbNodeSocket()->name, "Image");
}
testSocketLink(converter,
context,
output,
operation,
scene,
layerId,
is_preview);
}
}
void RenderLayersNode::missingSocketLink(NodeConverter &converter,
NodeOutput *output) const
{
NodeOperation *operation;
switch (output->getDataType()) {
case COM_DT_COLOR:
{
const float color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
SetColorOperation *color_operation = new SetColorOperation();
color_operation->setChannels(color);
operation = color_operation;
break;
}
case COM_DT_VECTOR:
{
const float vector[3] = {0.0f, 0.0f, 0.0f};
SetVectorOperation *vector_operation = new SetVectorOperation();
vector_operation->setVector(vector);
operation = vector_operation;
break;
}
case COM_DT_VALUE:
{
SetValueOperation *value_operation = new SetValueOperation();
value_operation->setValue(0.0f);
operation = value_operation;
break;
}
}
converter.mapOutputSocket(output, operation->getOutputSocket());
converter.addOperation(operation);
}
void RenderLayersNode::missingRenderLink(NodeConverter &converter) const
{
const int num_outputs = this->getNumberOfOutputSockets();
for (int i = 0; i < num_outputs; i++) {
NodeOutput *output = this->getOutputSocket(i);
missingSocketLink(converter, output);
}
}
void RenderLayersNode::convertToOperations(NodeConverter &converter,
const CompositorContext &context) const
{
Scene *scene = (Scene *)this->getbNode()->id;
Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL;
if (re != NULL) {
testRenderLink(converter, context, re);
RE_ReleaseResult(re);
}
else {
missingRenderLink(converter);
}
}

@ -24,6 +24,8 @@
#include "DNA_node_types.h"
#include "COM_RenderLayersProg.h"
struct Render;
/**
* @brief RenderLayersNode
* @ingroup Node
@ -31,7 +33,8 @@
class RenderLayersNode : public Node {
public:
RenderLayersNode(bNode *editorNode);
void convertToOperations(NodeConverter &converter, const CompositorContext &context) const;
void convertToOperations(NodeConverter &converter,
const CompositorContext &context) const;
private:
void testSocketLink(NodeConverter &converter,
const CompositorContext &context,
@ -40,4 +43,11 @@ private:
Scene *scene,
int layerId,
bool is_preview) const;
void testRenderLink(NodeConverter &converter,
const CompositorContext &context,
Render *re) const;
void missingSocketLink(NodeConverter &converter,
NodeOutput *output) const;
void missingRenderLink(NodeConverter &converter) const;
};

@ -125,6 +125,15 @@ typedef struct bAnimListElem {
void *key_data; /* motion data - mostly F-Curves, but can be other types too */
/* NOTE: id here is the "IdAdtTemplate"-style datablock (e.g. Object, Material, Texture, NodeTree)
* from which evaluation of the RNA-paths takes place. It's used to figure out how deep
* channels should be nested (e.g. for Textures/NodeTrees) in the tree, and allows property
* lookups (e.g. for sliders and for inserting keyframes) to work. If we had instead used
* bAction or something similar, none of this would be possible: although it's trivial
* to use an IdAdtTemplate type to find the source action a channel (e.g. F-Curve) comes from
* (i.e. in the AnimEditors, it *must* be the active action, as only that can be edited),
* it's impossible to go the other way (i.e. one action may be used in multiple places).
*/
struct ID *id; /* ID block that channel is attached to */
struct AnimData *adt; /* source of the animation data attached to ID block (for convenience) */

@ -627,7 +627,9 @@ static Mesh *bake_mesh_new_from_object(EvaluationContext *eval_ctx, Main *bmain,
ED_object_editmode_load(ob);
Mesh *me = BKE_mesh_new_from_object(eval_ctx, bmain, scene, ob, 1, 2, 0, 0);
BKE_mesh_split_faces(me, true);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
}
return me;
}

@ -2154,8 +2154,9 @@ static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNo
if (node->custom1 == 0) {
const float backdropWidth = backdrop->x;
const float backdropHeight = backdrop->y;
const float cx = x + snode->zoom * backdropWidth * node->custom3;
const float cx = x + snode->zoom * backdropWidth * node->custom3;
const float cy = y + snode->zoom * backdropHeight * node->custom4;
const float cross_size = 12 * U.pixelsize;
Gwn_VertFormat *format = immVertexFormat();
unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
@ -2165,10 +2166,10 @@ static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNo
immUniformColor3f(1.0f, 1.0f, 1.0f);
immBegin(GWN_PRIM_LINES, 4);
immVertex2f(pos, cx - 25, cy - 25);
immVertex2f(pos, cx + 25, cy + 25);
immVertex2f(pos, cx + 25, cy - 25);
immVertex2f(pos, cx - 25, cy + 25);
immVertex2f(pos, cx - cross_size, cy - cross_size);
immVertex2f(pos, cx + cross_size, cy + cross_size);
immVertex2f(pos, cx + cross_size, cy - cross_size);
immVertex2f(pos, cx - cross_size, cy + cross_size);
immEnd();
immUnbindProgram();

@ -267,9 +267,10 @@ void rna_PropertyGroup_unregister(Main *UNUSED(bmain), StructRNA *type)
RNA_struct_free(&BLENDER_RNA, type);
}
StructRNA *rna_PropertyGroup_register(Main *UNUSED(bmain), ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc UNUSED(call),
StructFreeFunc UNUSED(free))
StructRNA *rna_PropertyGroup_register(
Main *UNUSED(bmain), ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc UNUSED(call),
StructFreeFunc UNUSED(free))
{
PointerRNA dummyptr;

@ -247,8 +247,9 @@ static void rna_KeyingSetInfo_unregister(Main *bmain, StructRNA *type)
ANIM_keyingset_info_unregister(bmain, ksi);
}
static StructRNA *rna_KeyingSetInfo_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
static StructRNA *rna_KeyingSetInfo_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
KeyingSetInfo dummyksi = {NULL};
KeyingSetInfo *ksi;

@ -310,8 +310,9 @@ static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
BLI_freelinkN(&R_engines, et);
}
static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
static StructRNA *rna_RenderEngine_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
RenderEngineType *et, dummyet = {NULL};
RenderEngine dummyengine = {NULL};

@ -185,8 +185,9 @@ static void rna_Panel_unregister(Main *UNUSED(bmain), StructRNA *type)
WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
static StructRNA *rna_Panel_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
ARegionType *art;
PanelType *pt, dummypt = {NULL};
@ -469,8 +470,9 @@ static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
static StructRNA *rna_UIList_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
uiListType *ult, dummyult = {NULL};
uiList dummyuilist = {NULL};
@ -571,8 +573,9 @@ static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_Header_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
static StructRNA *rna_Header_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
ARegionType *art;
HeaderType *ht, dummyht = {NULL};
@ -699,8 +702,9 @@ static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
static StructRNA *rna_Menu_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
MenuType *mt, dummymt = {NULL};
Menu dummymenu = {NULL};

@ -591,8 +591,9 @@ static void rna_AddonPref_unregister(Main *UNUSED(bmain), StructRNA *type)
WM_main_add_notifier(NC_WINDOW, NULL);
}
static StructRNA *rna_AddonPref_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
static StructRNA *rna_AddonPref_register(
Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bAddonPrefType *apt, dummyapt = {{'\0'}};
bAddon dummyaddon = {NULL};

@ -1564,20 +1564,13 @@ void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *
vy0= ((double)my2)*vyd + (double)xx1;
/* correct span */
sn1= (my0 + my2)/2;
if (zspan->span1[sn1] < zspan->span2[sn1]) {
span1= zspan->span1+my2;
span2= zspan->span2+my2;
}
else {
span1= zspan->span2+my2;
span2= zspan->span1+my2;
}
span1= zspan->span1+my2;
span2= zspan->span2+my2;
for (i = 0, y = my2; y >= my0; i++, y--, span1--, span2--) {
sn1= floor(*span1);
sn2= floor(*span2);
sn1= floor(min_ff(*span1, *span2));
sn2= floor(max_ff(*span1, *span2));
sn1++;
if (sn2>=rectx) sn2= rectx-1;

@ -534,6 +534,7 @@ if(WITH_CYCLES)
if(WITH_OPENGL_TESTS)
add_cycles_render_test(opengl)
endif()
add_cycles_render_test(bake)
add_cycles_render_test(denoise)
add_cycles_render_test(displacement)
add_cycles_render_test(image_data_types)

@ -77,6 +77,22 @@ def render_file(filepath):
'--python', os.path.join(basedir,
"util",
"render_opengl.py")]
elif subject == 'bake':
command = [
BLENDER,
"-b",
"-noaudio",
"--factory-startup",
"--enable-autoexec",
filepath,
"-E", "CYCLES"]
command += custom_args
command += [
"-o", TEMP_FILE_MASK,
"-F", "PNG",
'--python', os.path.join(basedir,
"util",
"render_bake.py")]
else:
command = [
BLENDER,
@ -142,7 +158,7 @@ def test_get_images(filepath):
os.makedirs(diff_dirpath)
diff_img = os.path.join(diff_dirpath, testname + ".diff.png")
return ref_img, new_img, diff_img
return old_img, ref_img, new_img, diff_img
class Report:
@ -239,7 +255,7 @@ class Report:
name = test_get_name(filepath)
name = name.replace('_', ' ')
ref_img, new_img, diff_img = test_get_images(filepath)
old_img, ref_img, new_img, diff_img = test_get_images(filepath)
status = error if error else ""
style = """ style="background-color: #f99;" """ if error else ""
@ -266,7 +282,7 @@ class Report:
def verify_output(report, filepath):
ref_img, new_img, diff_img = test_get_images(filepath)
old_img, ref_img, new_img, diff_img = test_get_images(filepath)
# copy new image
if os.path.exists(new_img):
@ -274,25 +290,35 @@ def verify_output(report, filepath):
if os.path.exists(TEMP_FILE):
shutil.copy(TEMP_FILE, new_img)
update = os.getenv('CYCLESTEST_UPDATE')
if not os.path.exists(ref_img):
return False
if os.path.exists(ref_img):
# diff test with threshold
command = (
IDIFF,
"-fail", "0.016",
"-failpercent", "1",
ref_img,
TEMP_FILE,
)
try:
subprocess.check_output(command)
failed = False
except subprocess.CalledProcessError as e:
if VERBOSE:
print_message(e.output.decode("utf-8"))
failed = e.returncode != 1
else:
if not update:
return False
# diff test with threshold
command = (
IDIFF,
"-fail", "0.016",
"-failpercent", "1",
ref_img,
TEMP_FILE,
)
try:
subprocess.check_output(command)
failed = True
if failed and update:
# update reference
shutil.copy(new_img, ref_img)
shutil.copy(new_img, old_img)
failed = False
except subprocess.CalledProcessError as e:
if VERBOSE:
print_message(e.output.decode("utf-8"))
failed = e.returncode != 1
# generate diff image
command = (