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_shader.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_shader.h')
-rw-r--r--intern/cycles/kernel/kernel_shader.h460
1 files changed, 460 insertions, 0 deletions
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
new file mode 100644
index 00000000000..f1abbda7ae5
--- /dev/null
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -0,0 +1,460 @@
+/*
+ * 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.
+ */
+
+/*
+ * ShaderData, used in four steps:
+ *
+ * Setup from incoming ray, sampled position and background.
+ * Execute for surface, volume or displacement.
+ * Evaluate one or more closures.
+ * Release.
+ *
+ */
+
+#include "svm/bsdf.h"
+#include "svm/emissive.h"
+#include "svm/volume.h"
+#include "svm/svm_bsdf.h"
+#include "svm/svm.h"
+
+#ifdef WITH_OSL
+#include "osl_shader.h"
+#endif
+
+CCL_NAMESPACE_BEGIN
+
+/* ShaderData setup from incoming ray */
+
+__device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
+ const Intersection *isect, const Ray *ray)
+{
+ /* fetch triangle data */
+ int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ float4 Ns = kernel_tex_fetch(__tri_normal, prim);
+ float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
+ int shader = __float_as_int(Ns.w);
+
+ /* vectors */
+ sd->P = bvh_triangle_refine(kg, isect, ray);
+ sd->Ng = Ng;
+ sd->N = Ng;
+ sd->I = -ray->D;
+ sd->shader = shader;
+ sd->flag = 0;
+
+ /* triangle */
+#ifdef __INSTANCING__
+ sd->object = isect->object;
+#endif
+ sd->prim = prim;
+#ifdef __UV__
+ sd->u = isect->u;
+ sd->v = isect->v;
+#endif
+
+ /* smooth normal */
+ if(sd->shader < 0) {
+ sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+ sd->shader = -sd->shader;
+ }
+
+#ifdef __DPDU__
+ /* dPdu/dPdv */
+ triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
+#endif
+
+#ifdef __INSTANCING__
+ if(sd->object != ~0) {
+ /* instance transform */
+ object_normal_transform(kg, sd->object, &sd->N);
+ object_normal_transform(kg, sd->object, &sd->Ng);
+#ifdef __DPDU__
+ object_dir_transform(kg, sd->object, &sd->dPdu);
+ object_dir_transform(kg, sd->object, &sd->dPdv);
+#endif
+ }
+ else {
+ /* non-instanced object index */
+ sd->object = kernel_tex_fetch(__prim_object, isect->prim);
+ }
+#endif
+
+ /* backfacing test */
+ bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
+
+ if(backfacing) {
+ sd->flag = SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
+#ifdef __DPDU__
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
+#endif
+ }
+
+#ifdef __RAY_DIFFERENTIALS__
+ /* differentials */
+ differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t);
+ differential_incoming(&sd->dI, ray->dD);
+ differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
+#endif
+}
+
+/* ShaderData setup from position sampled on mesh */
+
+__device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
+ const float3 P, const float3 Ng, const float3 I,
+ int shader, int object, int prim, float u, float v)
+{
+ /* vectors */
+ sd->P = P;
+ sd->N = Ng;
+ sd->Ng = Ng;
+ sd->I = I;
+ sd->shader = shader;
+ sd->flag = 0;
+
+ /* primitive */
+#ifdef __INSTANCING__
+ sd->object = object;
+#endif
+ sd->prim = prim;
+#ifdef __UV__
+ sd->u = u;
+ sd->v = v;
+#endif
+
+ /* detect instancing, for non-instanced the object index is -object-1 */
+ bool instanced = false;
+
+ if(sd->prim != ~0) {
+ if(sd->object >= 0)
+ instanced = true;
+ else
+ sd->object = -sd->object-1;
+ }
+
+ /* smooth normal */
+ if(sd->shader < 0) {
+ sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
+ sd->shader = -sd->shader;
+
+#ifdef __INSTANCING__
+ if(instanced)
+ object_normal_transform(kg, sd->object, &sd->N);
+#endif
+ }
+
+#ifdef __DPDU__
+ /* dPdu/dPdv */
+ if(sd->prim == ~0) {
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else {
+ triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
+
+#ifdef __INSTANCING__
+ if(instanced) {
+ object_dir_transform(kg, sd->object, &sd->dPdu);
+ object_dir_transform(kg, sd->object, &sd->dPdv);
+ }
+#endif
+ }
+#endif
+
+ /* backfacing test */
+ if(sd->prim != ~0) {
+ bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
+
+ if(backfacing) {
+ sd->flag = SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
+#ifdef __DPDU__
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
+#endif
+ }
+ }
+
+#ifdef __RAY_DIFFERENTIALS__
+ /* no ray differentials here yet */
+ sd->dP.dx = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dP.dy = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dI.dx = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dI.dy = make_float3(0.0f, 0.0f, 0.0f);
+ sd->du.dx = 0.0f;
+ sd->du.dy = 0.0f;
+ sd->dv.dx = 0.0f;
+ sd->dv.dy = 0.0f;
+#endif
+}
+
+/* ShaderData setup for displacement */
+
+__device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
+ int object, int prim, float u, float v)
+{
+ float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f);
+ int shader;
+
+ P = triangle_point_MT(kg, prim, u, v);
+ Ng = triangle_normal_MT(kg, prim, &shader);
+
+ /* force smooth shading for displacement */
+ if(shader >= 0)
+ shader = -shader;
+
+ /* watch out: no instance transform currently */
+
+ shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v);
+}
+
+/* ShaderData setup from ray into background */
+
+__device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray)
+{
+ /* vectors */
+ sd->P = ray->D;
+ sd->N = -sd->P;
+ sd->Ng = -sd->P;
+ sd->I = -sd->P;
+ sd->shader = kernel_data.background.shader;
+ sd->flag = 0;
+
+#ifdef __INSTANCING__
+ sd->object = ~0;
+#endif
+ sd->prim = ~0;
+#ifdef __UV__
+ sd->u = 0.0f;
+ sd->v = 0.0f;
+#endif
+
+#ifdef __DPDU__
+ /* dPdu/dPdv */
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
+#endif
+
+#ifdef __RAY_DIFFERENTIALS__
+ /* differentials */
+ sd->dP = ray->dD;
+ differential_incoming(&sd->dI, sd->dP);
+ sd->du.dx = 0.0f;
+ sd->du.dy = 0.0f;
+ sd->dv.dx = 0.0f;
+ sd->dv.dy = 0.0f;
+#endif
+}
+
+/* BSDF */
+
+__device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
+ float randu, float randv, float3 *eval,
+ float3 *omega_in, differential3 *domega_in, float *pdf)
+{
+ int label;
+
+ *pdf = 0.0f;
+
+#ifdef WITH_OSL
+ if(kg->osl.use)
+ label = OSLShader::bsdf_sample(sd, randu, randv, *eval, *omega_in, *domega_in, *pdf);
+ else
+#endif
+ label = svm_bsdf_sample(sd, randu, randv, eval, omega_in, domega_in, pdf);
+
+ return label;
+}
+
+__device float3 shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
+ const float3 omega_in, float *pdf)
+{
+ float3 eval;
+
+ *pdf = 0.0f;
+
+#ifdef WITH_OSL
+ if(kg->osl.use)
+ eval = OSLShader::bsdf_eval(sd, omega_in, *pdf);
+ else
+#endif
+ eval = svm_bsdf_eval(sd, omega_in, pdf);
+
+ return eval;
+}
+
+__device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
+{
+#ifdef WITH_OSL
+ if(!kg->osl.use)
+#endif
+ svm_bsdf_blur(sd, roughness);
+}
+
+/* Emission */
+
+__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
+{
+#ifdef WITH_OSL
+ if(kg->osl.use) {
+ return OSLShader::emissive_eval(sd);
+ }
+ else
+#endif
+ {
+ return svm_emissive_eval(sd);
+ }
+}
+
+__device void shader_emissive_sample(KernelGlobals *kg, ShaderData *sd,
+ float randu, float randv, float3 *eval, float3 *I, float *pdf)
+{
+#ifdef WITH_OSL
+ if(kg->osl.use) {
+ OSLShader::emissive_sample(sd, randu, randv, eval, I, pdf);
+ }
+ else
+#endif
+ {
+ svm_emissive_sample(sd, randu, randv, eval, I, pdf);
+ }
+}
+
+/* Surface Evaluation */
+
+__device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
+ float randb, int path_flag)
+{
+#ifdef WITH_OSL
+ if(kg->osl.use) {
+ OSLShader::eval_surface(kg, sd, randb, path_flag);
+ }
+ else
+#endif
+ {
+#ifdef __SVM__
+ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
+#else
+ sd->svm_closure = CLOSURE_BSDF_DIFFUSE_ID;
+ sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f);
+#endif
+
+#ifdef __CAUSTICS_TRICKS__
+ /* caustic tricks */
+ if((path_flag & PATH_RAY_DIFFUSE) && (sd->flag & SD_BSDF_GLOSSY)) {
+ if(kernel_data.integrator.no_caustics) {
+ sd->flag &= ~(SD_BSDF_GLOSSY|SD_BSDF_HAS_EVAL|SD_EMISSION);
+ sd->svm_closure = NBUILTIN_CLOSURES;
+ sd->svm_closure_weight = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else if(kernel_data.integrator.blur_caustics > 0.0f)
+ shader_bsdf_blur(kg, sd, kernel_data.integrator.blur_caustics);
+ }
+#endif
+ }
+}
+
+/* Background Evaluation */
+
+__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
+{
+#ifdef WITH_OSL
+ if(kg->osl.use) {
+ return OSLShader::eval_background(kg, sd, path_flag);
+ }
+ else
+#endif
+ {
+#ifdef __SVM__
+ svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
+#else
+ sd->svm_closure_weight = make_float3(0.8f, 0.8f, 0.8f);
+#endif
+
+ return sd->svm_closure_weight;
+ }
+}
+
+/* Volume */
+
+__device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
+ float3 omega_in, float3 omega_out)
+{
+#ifdef WITH_OSL
+ if(kg->osl.use) {
+ OSLShader::volume_eval_phase(sd, omega_in, omega_out);
+ }
+ else
+#endif
+ {
+ return volume_eval_phase(sd, omega_in, omega_out);
+ }
+}
+
+/* Volume Evaluation */
+
+__device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
+ float randb, int path_flag)
+{
+#ifdef WITH_OSL
+ if(kg->osl.use) {
+ OSLShader::eval_volume(kg, sd, randb, path_flag);
+ }
+ else
+#endif
+ {
+#ifdef __SVM__
+ svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
+#endif
+ }
+}
+
+/* Displacement Evaluation */
+
+__device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
+{
+ /* this will modify sd->P */
+
+#ifdef WITH_OSL
+ if(kg->osl.use) {
+ OSLShader::eval_displacement(kg, sd);
+ }
+ else
+#endif
+ {
+#ifdef __SVM__
+ svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
+#endif
+ }
+}
+
+/* Free ShaderData */
+
+__device void shader_release(KernelGlobals *kg, ShaderData *sd)
+{
+#ifdef WITH_OSL
+ if(kg->osl.use)
+ OSLShader::release(kg, sd);
+#endif
+}
+
+CCL_NAMESPACE_END
+