Cycles: first step for implementation of non-progressive sampler that handles
direct and indirect lighting differently. Rather than picking one light for each point on the path, it now loops over all lights for direct lighting. For indirect lighting it still picks a random light each time. It gives control over the number of AA samples, and the number of Diffuse, Glossy, Transmission, AO, Mesh Light, Background and Lamp samples for each AA sample. This helps tuning render performance/noise and tends to give less noise for renders dominated by direct lighting. This sampling mode only works on the CPU, and still needs proper tile rendering to show progress (will follow tommorrow or so), because each AA sample can be quite slow now and so the delay between each update wil be too long.
This commit is contained in:
@@ -218,7 +218,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
|
||||
return result;
|
||||
}
|
||||
|
||||
__device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer)
|
||||
__device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer)
|
||||
{
|
||||
/* initialize */
|
||||
PathRadiance L;
|
||||
@@ -366,26 +366,15 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
|
||||
light_ray.time = sd.time;
|
||||
#endif
|
||||
|
||||
#ifdef __MULTI_LIGHT__
|
||||
/* index -1 means randomly sample from distribution */
|
||||
int i = (kernel_data.integrator.num_all_lights)? 0: -1;
|
||||
if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
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, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(&L, throughput, &L_light, shadow, state.bounce, is_lamp);
|
||||
}
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(&L, throughput, &L_light, shadow, state.bounce, is_lamp);
|
||||
}
|
||||
#ifdef __MULTI_LIGHT__
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -444,6 +433,451 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
|
||||
return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
|
||||
}
|
||||
|
||||
#ifdef __NON_PROGRESSIVE__
|
||||
|
||||
__device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer,
|
||||
float3 throughput, float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L)
|
||||
{
|
||||
/* path iteration */
|
||||
for(;; rng_offset += PRNG_BOUNCE_NUM) {
|
||||
/* intersect scene */
|
||||
Intersection isect;
|
||||
uint visibility = path_state_ray_visibility(kg, &state);
|
||||
|
||||
if(!scene_intersect(kg, &ray, visibility, &isect)) {
|
||||
#ifdef __BACKGROUND__
|
||||
/* sample background shader */
|
||||
float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf);
|
||||
path_radiance_accum_background(L, throughput, L_background, state.bounce);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* setup shading */
|
||||
ShaderData sd;
|
||||
shader_setup_from_ray(kg, &sd, &isect, &ray);
|
||||
float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF);
|
||||
shader_eval_surface(kg, &sd, rbsdf, state.flag);
|
||||
shader_merge_closures(kg, &sd);
|
||||
|
||||
/* 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) {
|
||||
float blur_pdf = kernel_data.integrator.filter_glossy*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) {
|
||||
float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
|
||||
path_radiance_accum_emission(L, throughput, emission, state.bounce);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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 */
|
||||
float probability = path_state_terminate_probability(kg, &state, throughput);
|
||||
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
|
||||
|
||||
if(terminate >= probability)
|
||||
break;
|
||||
|
||||
throughput /= probability;
|
||||
|
||||
#ifdef __AO__
|
||||
/* ambient occlusion */
|
||||
if(kernel_data.integrator.use_ambient_occlusion) {
|
||||
/* todo: solve correlation */
|
||||
float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U);
|
||||
float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V);
|
||||
|
||||
float3 ao_D;
|
||||
float ao_pdf;
|
||||
|
||||
sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
|
||||
|
||||
if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
|
||||
Ray light_ray;
|
||||
float3 ao_shadow;
|
||||
|
||||
light_ray.P = ray_offset(sd.P, sd.Ng);
|
||||
light_ray.D = ao_D;
|
||||
light_ray.t = kernel_data.background.ao_distance;
|
||||
#ifdef __MOTION__
|
||||
light_ray.time = sd.time;
|
||||
#endif
|
||||
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
|
||||
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor;
|
||||
path_radiance_accum_ao(L, throughput, ao_bsdf, ao_shadow, state.bounce);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __EMISSION__
|
||||
if(kernel_data.integrator.use_direct_light) {
|
||||
/* sample illumination from lights to find path contribution */
|
||||
if(sd.flag & SD_BSDF_HAS_EVAL) {
|
||||
float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT);
|
||||
float light_o = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_F);
|
||||
float light_u = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_U);
|
||||
float light_v = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_V);
|
||||
|
||||
Ray light_ray;
|
||||
BsdfEval L_light;
|
||||
bool is_lamp;
|
||||
|
||||
#ifdef __MOTION__
|
||||
light_ray.time = sd.time;
|
||||
#endif
|
||||
|
||||
/* sample random light */
|
||||
if(direct_emission(kg, &sd, -1, light_t, light_o, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(L, throughput, &L_light, shadow, state.bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* no BSDF? we can stop here */
|
||||
if(!(sd.flag & SD_BSDF))
|
||||
break;
|
||||
|
||||
/* sample BSDF */
|
||||
float bsdf_pdf;
|
||||
BsdfEval bsdf_eval;
|
||||
float3 bsdf_omega_in;
|
||||
differential3 bsdf_domega_in;
|
||||
float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U);
|
||||
float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V);
|
||||
int label;
|
||||
|
||||
label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
|
||||
&bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
|
||||
|
||||
shader_release(kg, &sd);
|
||||
|
||||
if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
|
||||
break;
|
||||
|
||||
/* modify throughput */
|
||||
path_radiance_bsdf_bounce(L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label);
|
||||
|
||||
/* set labels */
|
||||
if(!(label & LABEL_TRANSPARENT)) {
|
||||
ray_pdf = bsdf_pdf;
|
||||
min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
|
||||
}
|
||||
|
||||
/* update path state */
|
||||
path_state_next(kg, &state, label);
|
||||
|
||||
/* setup ray */
|
||||
ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
|
||||
ray.D = bsdf_omega_in;
|
||||
ray.t = FLT_MAX;
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
ray.dP = sd.dP;
|
||||
ray.dD = bsdf_domega_in;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
__device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer)
|
||||
{
|
||||
/* initialize */
|
||||
PathRadiance L;
|
||||
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
|
||||
float L_transparent = 0.0f;
|
||||
|
||||
path_radiance_init(&L, kernel_data.film.use_light_pass);
|
||||
|
||||
float ray_pdf = 0.0f;
|
||||
PathState state;
|
||||
int rng_offset = PRNG_BASE_NUM;
|
||||
|
||||
path_state_init(&state);
|
||||
|
||||
for(;; rng_offset += PRNG_BOUNCE_NUM) {
|
||||
/* intersect scene */
|
||||
Intersection isect;
|
||||
uint visibility = path_state_ray_visibility(kg, &state);
|
||||
|
||||
if(!scene_intersect(kg, &ray, visibility, &isect)) {
|
||||
/* 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
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __BACKGROUND__
|
||||
/* sample background shader */
|
||||
float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf);
|
||||
path_radiance_accum_background(&L, throughput, L_background, state.bounce);
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* setup shading */
|
||||
ShaderData sd;
|
||||
shader_setup_from_ray(kg, &sd, &isect, &ray);
|
||||
float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF);
|
||||
shader_eval_surface(kg, &sd, rbsdf, state.flag);
|
||||
shader_merge_closures(kg, &sd);
|
||||
|
||||
kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput);
|
||||
|
||||
/* holdout */
|
||||
#ifdef __HOLDOUT__
|
||||
if((sd.flag & (SD_HOLDOUT|SD_HOLDOUT_MASK))) {
|
||||
if(kernel_data.background.transparent) {
|
||||
float3 holdout_weight;
|
||||
|
||||
if(sd.flag & SD_HOLDOUT_MASK)
|
||||
holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
|
||||
else
|
||||
shader_holdout_eval(kg, &sd);
|
||||
|
||||
/* any throughput is ok, should all be identical here */
|
||||
L_transparent += average(holdout_weight*throughput);
|
||||
}
|
||||
|
||||
if(sd.flag & SD_HOLDOUT_MASK)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __EMISSION__
|
||||
/* emission */
|
||||
if(sd.flag & SD_EMISSION) {
|
||||
float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
|
||||
path_radiance_accum_emission(&L, throughput, emission, state.bounce);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* transparency termination */
|
||||
if(state.flag & PATH_RAY_TRANSPARENT) {
|
||||
/* 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 */
|
||||
float probability = path_state_terminate_probability(kg, &state, throughput);
|
||||
float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
|
||||
|
||||
if(terminate >= probability)
|
||||
break;
|
||||
|
||||
throughput /= probability;
|
||||
}
|
||||
|
||||
#ifdef __AO__
|
||||
/* ambient occlusion */
|
||||
if(kernel_data.integrator.use_ambient_occlusion) {
|
||||
int num_samples = kernel_data.integrator.ao_samples;
|
||||
float ao_factor = kernel_data.background.ao_factor/num_samples;
|
||||
|
||||
for(int j = 0; j < num_samples; j++) {
|
||||
/* todo: solve correlation */
|
||||
float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U);
|
||||
float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V);
|
||||
|
||||
float3 ao_D;
|
||||
float ao_pdf;
|
||||
|
||||
sample_cos_hemisphere(sd.N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
|
||||
|
||||
if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
|
||||
Ray light_ray;
|
||||
float3 ao_shadow;
|
||||
|
||||
light_ray.P = ray_offset(sd.P, sd.Ng);
|
||||
light_ray.D = ao_D;
|
||||
light_ray.t = kernel_data.background.ao_distance;
|
||||
#ifdef __MOTION__
|
||||
light_ray.time = sd.time;
|
||||
#endif
|
||||
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
|
||||
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*ao_factor;
|
||||
path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __EMISSION__
|
||||
/* sample illumination from lights to find path contribution */
|
||||
if(sd.flag & SD_BSDF_HAS_EVAL) {
|
||||
Ray light_ray;
|
||||
BsdfEval L_light;
|
||||
bool is_lamp;
|
||||
|
||||
#ifdef __MOTION__
|
||||
light_ray.time = sd.time;
|
||||
#endif
|
||||
|
||||
/* lamp sampling */
|
||||
for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) {
|
||||
int num_samples = light_select_num_samples(kg, i);
|
||||
float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights);
|
||||
|
||||
if(kernel_data.integrator.pdf_triangles != 0.0f)
|
||||
num_samples_inv *= 0.5f;
|
||||
|
||||
for(int j = 0; j < num_samples; j++) {
|
||||
float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U);
|
||||
float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V);
|
||||
|
||||
if(direct_emission(kg, &sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, state.bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* mesh light sampling */
|
||||
if(kernel_data.integrator.pdf_triangles != 0.0f) {
|
||||
int num_samples = kernel_data.integrator.mesh_light_samples;
|
||||
float num_samples_inv = 1.0f/num_samples;
|
||||
|
||||
if(kernel_data.integrator.num_all_lights)
|
||||
num_samples_inv *= 0.5f;
|
||||
|
||||
for(int j = 0; j < num_samples; j++) {
|
||||
float light_t = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT);
|
||||
float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U);
|
||||
float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V);
|
||||
|
||||
/* only sample triangle lights */
|
||||
if(kernel_data.integrator.num_all_lights)
|
||||
light_t = 0.5f*light_t;
|
||||
|
||||
if(direct_emission(kg, &sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) {
|
||||
/* trace shadow ray */
|
||||
float3 shadow;
|
||||
|
||||
if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
|
||||
/* accumulate */
|
||||
path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, state.bounce, is_lamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int i = 0; i< sd.num_closure; i++) {
|
||||
const ShaderClosure *sc = &sd.closure[i];
|
||||
|
||||
if(!CLOSURE_IS_BSDF(sc->type))
|
||||
continue;
|
||||
/* transparency is not handled here, but in outer loop */
|
||||
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID)
|
||||
continue;
|
||||
|
||||
int num_samples;
|
||||
|
||||
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
|
||||
num_samples = kernel_data.integrator.diffuse_samples;
|
||||
else if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
|
||||
num_samples = kernel_data.integrator.glossy_samples;
|
||||
else
|
||||
num_samples = kernel_data.integrator.transmission_samples;
|
||||
|
||||
float num_samples_inv = 1.0f/num_samples;
|
||||
|
||||
for(int j = 0; j < num_samples; j++) {
|
||||
/* sample BSDF */
|
||||
float bsdf_pdf;
|
||||
BsdfEval bsdf_eval;
|
||||
float3 bsdf_omega_in;
|
||||
differential3 bsdf_domega_in;
|
||||
float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U);
|
||||
float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V);
|
||||
int label;
|
||||
|
||||
label = shader_bsdf_sample_closure(kg, &sd, sc, bsdf_u, bsdf_v, &bsdf_eval,
|
||||
&bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
|
||||
|
||||
if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
|
||||
continue;
|
||||
|
||||
/* modify throughput */
|
||||
float3 tp = throughput;
|
||||
path_radiance_bsdf_bounce(&L, &tp, &bsdf_eval, bsdf_pdf, state.bounce, label);
|
||||
|
||||
/* set labels */
|
||||
float min_ray_pdf = FLT_MAX;
|
||||
|
||||
if(!(label & LABEL_TRANSPARENT))
|
||||
min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
|
||||
|
||||
/* modify path state */
|
||||
PathState ps = state;
|
||||
path_state_next(kg, &ps, label);
|
||||
|
||||
/* setup ray */
|
||||
ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
|
||||
ray.D = bsdf_omega_in;
|
||||
ray.t = FLT_MAX;
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
ray.dP = sd.dP;
|
||||
ray.dD = bsdf_domega_in;
|
||||
#endif
|
||||
|
||||
kernel_path_indirect(kg, rng, sample*num_samples, ray, buffer,
|
||||
tp*num_samples_inv, min_ray_pdf, ray_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L);
|
||||
}
|
||||
}
|
||||
|
||||
/* continue in case of transparency */
|
||||
throughput *= shader_bsdf_transparency(kg, &sd);
|
||||
shader_release(kg, &sd);
|
||||
|
||||
if(is_zero(throughput))
|
||||
break;
|
||||
|
||||
path_state_next(kg, &state, LABEL_TRANSPARENT);
|
||||
ray.P = ray_offset(sd.P, -sd.Ng);
|
||||
}
|
||||
|
||||
float3 L_sum = path_radiance_sum(kg, &L);
|
||||
|
||||
#ifdef __CLAMP_SAMPLE__
|
||||
path_radiance_clamp(&L, &L_sum, kernel_data.integrator.sample_clamp);
|
||||
#endif
|
||||
|
||||
kernel_write_light_passes(kg, buffer, &L, sample);
|
||||
|
||||
return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__device void kernel_path_trace(KernelGlobals *kg,
|
||||
__global float *buffer, __global uint *rng_state,
|
||||
int sample, int x, int y, int offset, int stride)
|
||||
@@ -480,8 +914,16 @@ __device void kernel_path_trace(KernelGlobals *kg,
|
||||
/* integrate */
|
||||
float4 L;
|
||||
|
||||
if (ray.t != 0.f)
|
||||
L = kernel_path_integrate(kg, &rng, sample, ray, buffer);
|
||||
if (ray.t != 0.0f) {
|
||||
#ifdef __NON_PROGRESSIVE__
|
||||
if(kernel_data.integrator.progressive)
|
||||
#endif
|
||||
L = kernel_path_progressive(kg, &rng, sample, ray, buffer);
|
||||
#ifdef __NON_PROGRESSIVE__
|
||||
else
|
||||
L = kernel_path_non_progressive(kg, &rng, sample, ray, buffer);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
L = make_float4(0.f, 0.f, 0.f, 0.f);
|
||||
|
||||
|
Reference in New Issue
Block a user