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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2012-01-25 21:23:52 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-01-25 21:23:52 +0400
commitf99343d3b8676543e2bd6acd6ee2274c21b1b388 (patch)
treefd40cd33691a783f82cf877e774d1b3a64d91ed3 /intern/cycles/kernel/kernel_accumulate.h
parent14f475fccad7158098ddecc285c617f990b2f8b5 (diff)
Cycles: Render Passes
Currently supported passes: * Combined, Z, Normal, Object Index, Material Index, Emission, Environment, Diffuse/Glossy/Transmission x Direct/Indirect/Color Not supported yet: * UV, Vector, Mist Only enabled for CPU devices at the moment, will do GPU tweaks tommorrow, also for environment importance sampling. Documentation: http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Passes
Diffstat (limited to 'intern/cycles/kernel/kernel_accumulate.h')
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h283
1 files changed, 283 insertions, 0 deletions
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
new file mode 100644
index 00000000000..e71fad58c96
--- /dev/null
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -0,0 +1,283 @@
+/*
+ * 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* BSDF Eval
+ *
+ * BSDF evaluation result, split per BSDF type. This is used to accumulate
+ * render passes separately. */
+
+__device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
+{
+#ifdef __PASSES__
+ eval->use_light_pass = use_light_pass;
+
+ if(eval->use_light_pass) {
+ eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
+ eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
+ eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
+
+ if(type == CLOSURE_BSDF_TRANSPARENT_ID)
+ eval->transparent = value;
+ else if(CLOSURE_IS_BSDF_DIFFUSE(type))
+ eval->diffuse = value;
+ else if(CLOSURE_IS_BSDF_GLOSSY(type))
+ eval->glossy = value;
+ else
+ eval->transmission = value;
+ }
+ else
+ eval->diffuse = value;
+#else
+ *eval = value;
+#endif
+}
+
+__device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
+{
+#ifdef __PASSES__
+ if(eval->use_light_pass) {
+ if(CLOSURE_IS_BSDF_DIFFUSE(type))
+ eval->diffuse += value;
+ else if(CLOSURE_IS_BSDF_GLOSSY(type))
+ eval->glossy += value;
+ else
+ eval->transmission += value;
+
+ /* skipping transparent, this function is used by for eval(), will be zero then */
+ }
+ else
+ eval->diffuse += value;
+#else
+ *eval += value;
+#endif
+}
+
+__device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
+{
+#ifdef __PASSES__
+ if(eval->use_light_pass) {
+ return is_zero(eval->diffuse)
+ && is_zero(eval->glossy)
+ && is_zero(eval->transmission)
+ && is_zero(eval->transparent);
+ }
+ else
+ return is_zero(eval->diffuse);
+#else
+ return is_zero(*eval);
+#endif
+}
+
+__device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
+{
+#ifdef __PASSES__
+ if(eval->use_light_pass) {
+ eval->diffuse *= value;
+ eval->glossy *= value;
+ eval->transmission *= value;
+
+ /* skipping transparent, this function is used by for eval(), will be zero then */
+ }
+ else
+ eval->diffuse *= value;
+#else
+ *eval *= value;
+#endif
+}
+
+/* Path Radiance
+ *
+ * We accumulate different render passes separately. After summing at the end
+ * to get the combined result, it should be identical. We definte directly
+ * visible as the first non-transparent hit, while indirectly visible are the
+ * bounces after that. */
+
+__device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
+{
+ /* clear all */
+#ifdef __PASSES__
+ L->use_light_pass = use_light_pass;
+
+ if(use_light_pass) {
+ L->indirect = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_throughput = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
+ L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
+
+ L->emission = make_float3(0.0f, 0.0f, 0.0f);
+ L->background = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else
+ L->emission = make_float3(0.0f, 0.0f, 0.0f);
+#else
+ *L = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+}
+
+__device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughput,
+ BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
+{
+ float inverse_pdf = 1.0f/bsdf_pdf;
+
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ if(bounce == 0) {
+ if(bsdf_label & LABEL_TRANSPARENT) {
+ /* transparent bounce before first hit */
+ *throughput *= bsdf_eval->transparent*inverse_pdf;
+ }
+ else {
+ /* first on directly visible surface */
+ float3 value = *throughput*inverse_pdf;
+
+ L->indirect_diffuse = bsdf_eval->diffuse*value;
+ L->indirect_glossy = bsdf_eval->glossy*value;
+ L->indirect_transmission = bsdf_eval->transmission*value;
+
+ *throughput = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
+
+ L->direct_throughput = *throughput;
+ }
+ }
+ else {
+ /* indirectly visible through BSDF */
+ float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent)*inverse_pdf;
+ *throughput *= sum;
+ }
+ }
+ else
+ *throughput *= bsdf_eval->diffuse*inverse_pdf;
+#else
+ *throughput *= *bsdf_eval*inverse_pdf;
+#endif
+}
+
+__device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ if(bounce == 0)
+ L->emission += throughput*value;
+ else if(bounce == 1)
+ L->direct_emission += throughput*value;
+ else
+ L->indirect += throughput*value;
+ }
+ else
+ L->emission += throughput*value;
+#else
+ *L += throughput*value;
+#endif
+}
+
+__device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, int bounce)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ if(bounce == 0) {
+ /* directly visible lighting */
+ L->direct_diffuse += throughput*bsdf_eval->diffuse;
+ L->direct_glossy += throughput*bsdf_eval->glossy;
+ L->direct_transmission += throughput*bsdf_eval->transmission;
+ }
+ else {
+ /* indirectly visible lighting after BSDF bounce */
+ float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission;
+ L->indirect += throughput*sum;
+ }
+ }
+ else
+ L->emission += throughput*bsdf_eval->diffuse;
+#else
+ *L += throughput*(*bsdf_eval);
+#endif
+}
+
+__device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ if(bounce == 0)
+ L->background += throughput*value;
+ else if(bounce == 1)
+ L->direct_emission += throughput*value;
+ else
+ L->indirect += throughput*value;
+ }
+ else
+ L->emission += throughput*value;
+#else
+ *L += throughput*value;
+#endif
+}
+
+__device_inline float3 safe_divide_color(float3 a, float3 b)
+{
+ float x, y, z;
+
+ x = (b.x != 0.0f)? a.x/b.x: 0.0f;
+ y = (b.y != 0.0f)? a.y/b.y: 0.0f;
+ z = (b.z != 0.0f)? a.z/b.z: 0.0f;
+
+ return make_float3(x, y, z);
+}
+
+__device_inline float3 path_radiance_sum(PathRadiance *L)
+{
+#ifdef __PASSES__
+ if(L->use_light_pass) {
+ /* this division is a bit ugly, but means we only have to keep track of
+ only a single throughput further along the path, here we recover just
+ the indirect parth that is not influenced by any particular BSDF type */
+ L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput);
+ L->direct_diffuse += L->indirect_diffuse*L->direct_emission;
+ L->direct_glossy += L->indirect_glossy*L->direct_emission;
+ L->direct_transmission += L->indirect_transmission*L->direct_emission;
+
+ L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
+ L->indirect_diffuse *= L->indirect;
+ L->indirect_glossy *= L->indirect;
+ L->indirect_transmission *= L->indirect;
+
+ return L->emission + L->background
+ + L->direct_diffuse + L->direct_glossy + L->direct_transmission
+ + L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
+ }
+ else
+ return L->emission;
+#else
+ return *L;
+#endif
+}
+
+CCL_NAMESPACE_END
+