Blender V2.61 - r43446

kernel_path.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "kernel_differential.h"
00020 #include "kernel_montecarlo.h"
00021 #include "kernel_triangle.h"
00022 #include "kernel_object.h"
00023 #ifdef __QBVH__
00024 #include "kernel_qbvh.h"
00025 #else
00026 #include "kernel_bvh.h"
00027 #endif
00028 #include "kernel_camera.h"
00029 #include "kernel_shader.h"
00030 #include "kernel_light.h"
00031 #include "kernel_emission.h"
00032 #include "kernel_random.h"
00033 
00034 CCL_NAMESPACE_BEGIN
00035 
00036 #ifdef __MODIFY_TP__
00037 __device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global float3 *buffer, int x, int y, int offset, int stride, int sample)
00038 {
00039     /* modify throughput to influence path termination probability, to avoid
00040        darker regions receiving fewer samples than lighter regions. also RGB
00041        are weighted differently. proper validation still remains to be done. */
00042     const float3 weights = make_float3(1.0f, 1.33f, 0.66f);
00043     const float3 one = make_float3(1.0f, 1.0f, 1.0f);
00044     const int minsample = 5;
00045     const float minL = 0.1f;
00046 
00047     if(sample >= minsample) {
00048         float3 L = buffer[offset + x + y*stride];
00049         float3 Lmin = make_float3(minL, minL, minL);
00050         float correct = (float)(sample+1)/(float)sample;
00051 
00052         L = film_map(L*correct, sample);
00053 
00054         return weights/clamp(L, Lmin, one);
00055     }
00056 
00057     return weights;
00058 }
00059 #endif
00060 
00061 typedef struct PathState {
00062     uint flag;
00063     int bounce;
00064 
00065     int diffuse_bounce;
00066     int glossy_bounce;
00067     int transmission_bounce;
00068     int transparent_bounce;
00069 } PathState;
00070 
00071 __device_inline void path_state_init(PathState *state)
00072 {
00073     state->flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
00074     state->bounce = 0;
00075     state->diffuse_bounce = 0;
00076     state->glossy_bounce = 0;
00077     state->transmission_bounce = 0;
00078     state->transparent_bounce = 0;
00079 }
00080 
00081 __device_inline void path_state_next(KernelGlobals *kg, PathState *state, int label)
00082 {
00083     /* ray through transparent keeps same flags from previous ray and is
00084        not counted as a regular bounce, transparent has separate max */
00085     if(label & LABEL_TRANSPARENT) {
00086         state->flag |= PATH_RAY_TRANSPARENT;
00087         state->transparent_bounce++;
00088 
00089         if(!kernel_data.integrator.transparent_shadows)
00090             state->flag |= PATH_RAY_MIS_SKIP;
00091 
00092         return;
00093     }
00094 
00095     state->bounce++;
00096 
00097     /* reflection/transmission */
00098     if(label & LABEL_REFLECT) {
00099         state->flag |= PATH_RAY_REFLECT;
00100         state->flag &= ~(PATH_RAY_TRANSMIT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
00101 
00102         if(label & LABEL_DIFFUSE)
00103             state->diffuse_bounce++;
00104         else
00105             state->glossy_bounce++;
00106     }
00107     else {
00108         kernel_assert(label & LABEL_TRANSMIT);
00109 
00110         state->flag |= PATH_RAY_TRANSMIT;
00111         state->flag &= ~(PATH_RAY_REFLECT|PATH_RAY_CAMERA|PATH_RAY_TRANSPARENT);
00112 
00113         state->transmission_bounce++;
00114     }
00115 
00116     /* diffuse/glossy/singular */
00117     if(label & LABEL_DIFFUSE) {
00118         state->flag |= PATH_RAY_DIFFUSE;
00119         state->flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
00120     }
00121     else if(label & LABEL_GLOSSY) {
00122         state->flag |= PATH_RAY_GLOSSY;
00123         state->flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP);
00124     }
00125     else {
00126         kernel_assert(label & LABEL_SINGULAR);
00127 
00128         state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
00129         state->flag &= ~PATH_RAY_DIFFUSE;
00130     }
00131 }
00132 
00133 __device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state)
00134 {
00135     uint flag = state->flag;
00136 
00137     /* for visibility, diffuse/glossy are for reflection only */
00138     if(flag & PATH_RAY_TRANSMIT)
00139         flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
00140     /* for camera visibility, use render layer flags */
00141     if(flag & PATH_RAY_CAMERA)
00142         flag |= kernel_data.integrator.layer_flag;
00143 
00144     return flag;
00145 }
00146 
00147 __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathState *state, const float3 throughput)
00148 {
00149     if(state->flag & PATH_RAY_TRANSPARENT) {
00150         /* transparent rays treated separately */
00151         if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce)
00152             return 0.0f;
00153         else if(state->transparent_bounce <= kernel_data.integrator.transparent_min_bounce)
00154             return 1.0f;
00155     }
00156     else {
00157         /* other rays */
00158         if((state->bounce >= kernel_data.integrator.max_bounce) ||
00159            (state->diffuse_bounce >= kernel_data.integrator.max_diffuse_bounce) ||
00160            (state->glossy_bounce >= kernel_data.integrator.max_glossy_bounce) ||
00161            (state->transmission_bounce >= kernel_data.integrator.max_transmission_bounce))
00162             return 0.0f;
00163         else if(state->bounce <= kernel_data.integrator.min_bounce)
00164             return 1.0f;
00165     }
00166 
00167     /* probalistic termination */
00168     return average(throughput);
00169 }
00170 
00171 __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L)
00172 {
00173     if(ray->t == 0.0f)
00174         return false;
00175     
00176     bool result = scene_intersect(kg, ray, PATH_RAY_SHADOW_OPAQUE, isect);
00177 
00178 #ifdef __TRANSPARENT_SHADOWS__
00179     if(result && kernel_data.integrator.transparent_shadows) {
00180         /* transparent shadows work in such a way to try to minimize overhead
00181            in cases where we don't need them. after a regular shadow ray is
00182            cast we check if the hit primitive was potentially transparent, and
00183            only in that case start marching. this gives on extra ray cast for
00184            the cases were we do want transparency.
00185            
00186            also note that for this to work correct, multi close sampling must
00187            be used, since we don't pass a random number to shader_eval_surface */
00188         if(shader_transparent_shadow(kg, isect)) {
00189             float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
00190             float3 Pend = ray->P + ray->D*ray->t;
00191             int bounce = state->transparent_bounce;
00192 
00193             for(;;) {
00194                 if(bounce >= kernel_data.integrator.transparent_max_bounce) {
00195                     return true;
00196                 }
00197                 else if(bounce >= kernel_data.integrator.transparent_min_bounce) {
00198                     /* todo: get random number somewhere for probabilistic terminate */
00199 #if 0
00200                     float probability = average(throughput);
00201                     float terminate = 0.0f;
00202 
00203                     if(terminate >= probability)
00204                         return true;
00205 
00206                     throughput /= probability;
00207 #endif
00208                 }
00209 
00210                 if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect)) {
00211                     *light_L *= throughput;
00212                     return false;
00213                 }
00214 
00215                 if(!shader_transparent_shadow(kg, isect))
00216                     return true;
00217 
00218                 ShaderData sd;
00219                 shader_setup_from_ray(kg, &sd, isect, ray);
00220                 shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW);
00221 
00222                 throughput *= shader_bsdf_transparency(kg, &sd);
00223 
00224                 ray->P = ray_offset(sd.P, -sd.Ng);
00225                 if(ray->t != FLT_MAX)
00226                     ray->D = normalize_len(Pend - ray->P, &ray->t);
00227 
00228                 bounce++;
00229             }
00230         }
00231     }
00232 #endif
00233 
00234     return result;
00235 }
00236 
00237 __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, float3 throughput)
00238 {
00239     /* initialize */
00240     float3 L = make_float3(0.0f, 0.0f, 0.0f);
00241     float Ltransparent = 0.0f;
00242 
00243 #ifdef __EMISSION__
00244     float ray_pdf = 0.0f;
00245 #endif
00246     PathState state;
00247     int rng_offset = PRNG_BASE_NUM;
00248 
00249     path_state_init(&state);
00250 
00251     /* path iteration */
00252     for(;; rng_offset += PRNG_BOUNCE_NUM) {
00253         /* intersect scene */
00254         Intersection isect;
00255         uint visibility = path_state_ray_visibility(kg, &state);
00256 
00257         if(!scene_intersect(kg, &ray, visibility, &isect)) {
00258             /* eval background shader if nothing hit */
00259             if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) {
00260                 Ltransparent += average(throughput);
00261             }
00262             else {
00263 #ifdef __BACKGROUND__
00264                 ShaderData sd;
00265                 shader_setup_from_background(kg, &sd, &ray);
00266                 L += throughput*shader_eval_background(kg, &sd, state.flag);
00267                 shader_release(kg, &sd);
00268 #else
00269                 L += throughput*make_float3(0.8f, 0.8f, 0.8f);
00270 #endif
00271             }
00272 
00273             break;
00274         }
00275 
00276         /* setup shading */
00277         ShaderData sd;
00278         shader_setup_from_ray(kg, &sd, &isect, &ray);
00279         float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF);
00280         shader_eval_surface(kg, &sd, rbsdf, state.flag);
00281 
00282 #ifdef __HOLDOUT__
00283         if((sd.flag & SD_HOLDOUT) && (state.flag & PATH_RAY_CAMERA)) {
00284             float3 holdout_weight = shader_holdout_eval(kg, &sd);
00285 
00286             if(kernel_data.background.transparent)
00287                 Ltransparent += average(holdout_weight*throughput);
00288         }
00289 #endif
00290 
00291 #ifdef __EMISSION__
00292         /* emission */
00293         if(sd.flag & SD_EMISSION)
00294             L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
00295 #endif
00296 
00297         /* path termination. this is a strange place to put the termination, it's
00298            mainly due to the mixed in MIS that we use. gives too many unneeded
00299            shader evaluations, only need emission if we are going to terminate */
00300         float probability = path_state_terminate_probability(kg, &state, throughput);
00301         float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE);
00302 
00303         if(terminate >= probability)
00304             break;
00305 
00306         throughput /= probability;
00307 
00308 #ifdef __EMISSION__
00309         if(kernel_data.integrator.use_direct_light) {
00310             /* sample illumination from lights to find path contribution */
00311             if(sd.flag & SD_BSDF_HAS_EVAL) {
00312                 float light_t = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT);
00313                 float light_o = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_F);
00314                 float light_u = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_U);
00315                 float light_v = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_V);
00316 
00317                 Ray light_ray;
00318                 float3 light_L;
00319 
00320 #ifdef __MULTI_LIGHT__
00321                 /* index -1 means randomly sample from distribution */
00322                 int i = (kernel_data.integrator.num_distribution)? -1: 0;
00323 
00324                 for(; i < kernel_data.integrator.num_all_lights; i++) {
00325 #else
00326                 const int i = -1;
00327 #endif
00328                     if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
00329                         /* trace shadow ray */
00330                         if(!shadow_blocked(kg, &state, &light_ray, &isect, &light_L))
00331                             L += throughput*light_L;
00332                     }
00333 #ifdef __MULTI_LIGHT__
00334                 }
00335 #endif
00336             }
00337         }
00338 #endif
00339 
00340         /* no BSDF? we can stop here */
00341         if(!(sd.flag & SD_BSDF))
00342             break;
00343 
00344         /* sample BSDF */
00345         float bsdf_pdf;
00346         float3 bsdf_eval;
00347         float3 bsdf_omega_in;
00348         differential3 bsdf_domega_in;
00349         float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U);
00350         float bsdf_v = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_V);
00351         int label;
00352 
00353         label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
00354             &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
00355 
00356         shader_release(kg, &sd);
00357 
00358         if(bsdf_pdf == 0.0f || is_zero(bsdf_eval))
00359             break;
00360 
00361         /* modify throughput */
00362         throughput *= bsdf_eval/bsdf_pdf;
00363 
00364         /* set labels */
00365 #ifdef __EMISSION__
00366         ray_pdf = bsdf_pdf;
00367 #endif
00368 
00369         /* update path state */
00370         path_state_next(kg, &state, label);
00371 
00372         /* setup ray */
00373         ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
00374         ray.D = bsdf_omega_in;
00375         ray.t = FLT_MAX;
00376 #ifdef __RAY_DIFFERENTIALS__
00377         ray.dP = sd.dP;
00378         ray.dD = bsdf_domega_in;
00379 #endif
00380     }
00381 
00382     return make_float4(L.x, L.y, L.z, 1.0f - Ltransparent);
00383 }
00384 
00385 __device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int sample, int x, int y, int offset, int stride)
00386 {
00387     /* initialize random numbers */
00388     RNG rng;
00389 
00390     float filter_u;
00391     float filter_v;
00392 
00393     path_rng_init(kg, rng_state, sample, &rng, x, y, offset, stride, &filter_u, &filter_v);
00394 
00395     /* sample camera ray */
00396     Ray ray;
00397 
00398     float lens_u = path_rng(kg, &rng, sample, PRNG_LENS_U);
00399     float lens_v = path_rng(kg, &rng, sample, PRNG_LENS_V);
00400 
00401     camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray);
00402 
00403     /* integrate */
00404 #ifdef __MODIFY_TP__
00405     float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, offset, stride, sample);
00406     float4 L = kernel_path_integrate(kg, &rng, sample, ray, throughput)/throughput;
00407 #else
00408     float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
00409     float4 L = kernel_path_integrate(kg, &rng, sample, ray, throughput);
00410 #endif
00411 
00412     /* accumulate result in output buffer */
00413     int index = offset + x + y*stride;
00414 
00415     if(sample == 0)
00416         buffer[index] = L;
00417     else
00418         buffer[index] += L;
00419 
00420     path_rng_end(kg, rng_state, rng, x, y, offset, stride);
00421 }
00422 
00423 CCL_NAMESPACE_END
00424