Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2011-04-27 15:58:34 +0400
committerTon Roosendaal <ton@blender.org>2011-04-27 15:58:34 +0400
commitda376e0237517543aa21740ee2363234ee1c20ae (patch)
tree014a513ed8d0eccc5e54fef42347781e85bae56a /intern/cycles/kernel/kernel_path.h
parent693780074388111e7b9ef1c3825e462f398dc6c4 (diff)
Cycles render engine, initial commit. This is the engine itself, blender modifications and build instructions will follow later.
Cycles uses code from some great open source projects, many thanks them: * BVH building and traversal code from NVidia's "Understanding the Efficiency of Ray Traversal on GPUs": http://code.google.com/p/understanding-the-efficiency-of-ray-traversal-on-gpus/ * Open Shading Language for a large part of the shading system: http://code.google.com/p/openshadinglanguage/ * Blender for procedural textures and a few other nodes. * Approximate Catmull Clark subdivision from NVidia Mesh tools: http://code.google.com/p/nvidia-mesh-tools/ * Sobol direction vectors from: http://web.maths.unsw.edu.au/~fkuo/sobol/ * Film response functions from: http://www.cs.columbia.edu/CAVE/software/softlib/dorf.php
Diffstat (limited to 'intern/cycles/kernel/kernel_path.h')
-rw-r--r--intern/cycles/kernel/kernel_path.h263
1 files changed, 263 insertions, 0 deletions
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
new file mode 100644
index 00000000000..15c7e67f101
--- /dev/null
+++ b/intern/cycles/kernel/kernel_path.h
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "kernel_differential.h"
+#include "kernel_montecarlo.h"
+#include "kernel_triangle.h"
+#include "kernel_object.h"
+#ifdef __QBVH__
+#include "kernel_qbvh.h"
+#else
+#include "kernel_bvh.h"
+#endif
+#include "kernel_camera.h"
+#include "kernel_shader.h"
+#include "kernel_light.h"
+#include "kernel_emission.h"
+#include "kernel_random.h"
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef __MODIFY_TP__
+__device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global float3 *buffer, int x, int y, int pass)
+{
+ /* modify throughput to influence path termination probability, to avoid
+ darker regions receiving fewer samples than lighter regions. also RGB
+ are weighted differently. proper validation still remains to be done. */
+ const float3 weights = make_float3(1.0f, 1.33f, 0.66f);
+ const float3 one = make_float3(1.0f, 1.0f, 1.0f);
+ const int minpass = 5;
+ const float minL = 0.1f;
+
+ if(pass >= minpass) {
+ float3 L = buffer[x + y*kernel_data.cam.width];
+ float3 Lmin = make_float3(minL, minL, minL);
+ float correct = (float)(pass+1)/(float)pass;
+
+ L = film_map(L*correct, pass);
+
+ return weights/clamp(L, Lmin, one);
+ }
+
+ return weights;
+}
+#endif
+
+__device float path_terminate_probability(KernelGlobals *kg, int bounce, const float3 throughput)
+{
+ if(bounce >= kernel_data.integrator.maxbounce)
+ return 0.0f;
+ else if(bounce <= kernel_data.integrator.minbounce)
+ return 1.0f;
+
+ return average(throughput);
+}
+
+__device int path_flag_from_label(int path_flag, int label)
+{
+ /* reflect/transmit */
+ if(label & LABEL_REFLECT) {
+ path_flag |= PATH_RAY_REFLECT;
+ path_flag &= ~PATH_RAY_TRANSMIT;
+ }
+ else {
+ kernel_assert(label & LABEL_TRANSMIT);
+
+ path_flag |= PATH_RAY_TRANSMIT;
+ path_flag &= ~PATH_RAY_REFLECT;
+ }
+
+ /* diffuse/glossy/singular */
+ if(label & LABEL_DIFFUSE) {
+ path_flag |= PATH_RAY_DIFFUSE;
+ path_flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR);
+ }
+ else if(label & LABEL_GLOSSY) {
+ path_flag |= PATH_RAY_GLOSSY;
+ path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR);
+ }
+ else {
+ kernel_assert(label & (LABEL_SINGULAR|LABEL_STRAIGHT));
+
+ path_flag |= PATH_RAY_SINGULAR;
+ path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
+ }
+
+ /* ray through transparent is still camera ray */
+ if(!(label & LABEL_STRAIGHT))
+ path_flag &= ~PATH_RAY_CAMERA;
+
+ return path_flag;
+}
+
+__device float3 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput)
+{
+ /* initialize */
+ float3 L = make_float3(0.0f, 0.0f, 0.0f);
+
+#ifdef __EMISSION__
+ float ray_pdf = 0.0f;
+#endif
+ int path_flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR;
+ int rng_offset = PRNG_BASE_NUM;
+
+ /* path iteration */
+ for(int bounce = 0; ; bounce++, rng_offset += PRNG_BOUNCE_NUM) {
+ /* intersect scene */
+ Intersection isect;
+
+ if(!scene_intersect(kg, &ray, false, &isect)) {
+ /* eval background shader if nothing hit */
+#ifdef __BACKGROUND__
+ ShaderData sd;
+ shader_setup_from_background(kg, &sd, &ray);
+ L += throughput*shader_eval_background(kg, &sd, path_flag);
+ shader_release(kg, &sd);
+#else
+ L += throughputmake_float3(0.8f, 0.8f, 0.8f);
+#endif
+ break;
+ }
+
+ /* setup shading */
+ ShaderData sd;
+ shader_setup_from_ray(kg, &sd, &isect, &ray);
+ float rbsdf = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF);
+ shader_eval_surface(kg, &sd, rbsdf, path_flag);
+
+#ifdef __EMISSION__
+ /* emission */
+ if(kernel_data.integrator.use_emission) {
+ if(sd.flag & SD_EMISSION)
+ L += throughput*indirect_emission(kg, &sd, isect.t, path_flag, ray_pdf);
+
+ /* sample illumination from lights to find path contribution */
+ if((sd.flag & SD_BSDF_HAS_EVAL) &&
+ bounce != kernel_data.integrator.maxbounce) {
+ float light_t = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT);
+ float light_o = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_F);
+ float light_u = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_U);
+ float light_v = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_V);
+
+ Ray light_ray;
+ float3 light_L;
+
+ if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
+ /* trace shadow ray */
+ if(!scene_intersect(kg, &light_ray, true, &isect))
+ L += throughput*light_L;
+ }
+ }
+ }
+#endif
+
+ /* sample BSDF */
+ float bsdf_pdf;
+ float3 bsdf_eval;
+ float3 bsdf_omega_in;
+ differential3 bsdf_domega_in;
+ float bsdf_u = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF_U);
+ float bsdf_v = path_rng(kg, rng, pass, 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 || is_zero(bsdf_eval))
+ break;
+
+ /* modify throughput */
+ throughput *= bsdf_eval/bsdf_pdf;
+
+ /* set labels */
+#ifdef __EMISSION__
+ ray_pdf = bsdf_pdf;
+#endif
+
+ path_flag = path_flag_from_label(path_flag, label);
+
+ /* path termination */
+ float probability = path_terminate_probability(kg, bounce, throughput);
+ float terminate = path_rng(kg, rng, pass, rng_offset + PRNG_TERMINATE);
+
+ if(terminate >= probability)
+ break;
+
+ throughput /= probability;
+
+ /* 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
+ }
+
+ return L;
+}
+
+__device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int pass, int x, int y)
+{
+ /* initialize random numbers */
+ RNG rng;
+
+ float filter_u;
+ float filter_v;
+
+ path_rng_init(kg, rng_state, pass, &rng, x, y, &filter_u, &filter_v);
+
+ /* sample camera ray */
+ Ray ray;
+
+ float lens_u = path_rng(kg, &rng, pass, PRNG_LENS_U);
+ float lens_v = path_rng(kg, &rng, pass, PRNG_LENS_V);
+
+ camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray);
+
+ /* integrate */
+#ifdef __MODIFY_TP__
+ float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, pass);
+ float3 L = kernel_path_integrate(kg, &rng, pass, ray, throughput)/throughput;
+#else
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 L = kernel_path_integrate(kg, &rng, pass, ray, throughput);
+#endif
+
+ /* accumulate result in output buffer */
+ int index = x + y*kernel_data.cam.width;
+
+ float4 result;
+ result.x = L.x;
+ result.y = L.y;
+ result.z = L.z;
+ result.w = 1.0f;
+
+ if(pass == 0)
+ buffer[index] = result;
+ else
+ buffer[index] += result;
+
+ path_rng_end(kg, rng_state, rng, x, y);
+}
+
+CCL_NAMESPACE_END
+