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-11-06 23:59:02 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2012-11-06 23:59:02 +0400
commit27d647dcf8c5d9ea46133761c899bce0860e0fa2 (patch)
tree8c3ef1e71c55f5e79be2a73a1650c2a61a50a8d2 /intern/cycles/kernel
parentccffb6811c9db614047e9dba0eb5e509609128dc (diff)
Cycles: 4 new nodes.
* Tangent: generate a tangent direction for anisotropic shading. Can be either radial around X/Y/Z axis, or from a UV map. The default tangent for the anisotropic BSDF and geometry node is now always radial Z, for UV tangent use this node now. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Tangent * Normal Map: generate a perturbed normal from an RGB normal map image. This is usually chained with an Image Texture node in the color input, to specify the normal map image. For tangent space normal maps, the UV coordinates for the image must match, and the image texture should be set to Non-Color mode to give correct results. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/More#Normal_Map * Refraction BSDF: for best results this node should be considered as a building block and not be used on its own, but rather mixed with a glossy node using a fresnel type factor. Otherwise it will give quite dark results at the edges for glossy refraction. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Shaders#Refraction * Ambient Occlusion: controls the amount of AO a surface receives, rather than having just a global factor in the world. Note that this outputs a shader and not a color, that's for another time. http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Shaders#Ambient_Occlusion
Diffstat (limited to 'intern/cycles/kernel')
-rw-r--r--intern/cycles/kernel/closure/bsdf_ward.h10
-rw-r--r--intern/cycles/kernel/kernel_path.h9
-rw-r--r--intern/cycles/kernel/kernel_shader.h21
-rw-r--r--intern/cycles/kernel/kernel_types.h13
-rw-r--r--intern/cycles/kernel/osl/background.cpp27
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h6
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp14
-rw-r--r--intern/cycles/kernel/shaders/CMakeLists.txt12
-rw-r--r--intern/cycles/kernel/shaders/node_ambient_occlusion.osl27
-rw-r--r--intern/cycles/kernel/shaders/node_geometry.osl21
-rw-r--r--intern/cycles/kernel/shaders/node_normal_map.osl48
-rw-r--r--intern/cycles/kernel/shaders/node_refraction_bsdf.osl39
-rw-r--r--intern/cycles/kernel/shaders/node_tangent.osl50
-rw-r--r--intern/cycles/kernel/shaders/node_ward_bsdf.osl8
-rw-r--r--intern/cycles/kernel/shaders/stdosl.h1
-rw-r--r--intern/cycles/kernel/svm/svm.h9
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h73
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h23
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h86
-rw-r--r--intern/cycles/kernel/svm/svm_types.h28
21 files changed, 464 insertions, 63 deletions
diff --git a/intern/cycles/kernel/closure/bsdf_ward.h b/intern/cycles/kernel/closure/bsdf_ward.h
index 9c81548a2c3..dbddcf20dba 100644
--- a/intern/cycles/kernel/closure/bsdf_ward.h
+++ b/intern/cycles/kernel/closure/bsdf_ward.h
@@ -68,7 +68,10 @@ __device float3 bsdf_ward_eval_reflect(const ShaderClosure *sc, const float3 I,
float cosNO = dot(N, I);
float cosNI = dot(N, omega_in);
- if(cosNI > 0 && cosNO > 0) {
+ if(cosNI > 0.0f && cosNO > 0.0f) {
+ cosNO = max(cosNO, 1e-4f);
+ cosNI = max(cosNI, 1e-4f);
+
// get half vector and get x,y basis on the surface for anisotropy
float3 H = normalize(omega_in + I); // normalize needed for pdf
float3 X, Y;
@@ -103,7 +106,7 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa
float3 T = sc->T;
float cosNO = dot(N, I);
- if(cosNO > 0) {
+ if(cosNO > 0.0f) {
// get x,y basis on the surface for anisotropy
float3 X, Y;
make_orthonormals_tangent(N, T, &X, &Y);
@@ -165,6 +168,9 @@ __device int bsdf_ward_sample(const ShaderClosure *sc, float3 Ng, float3 I, floa
if(dot(Ng, *omega_in) > 0) {
float cosNI = dot(N, *omega_in);
if(cosNI > 0) {
+ cosNO = max(cosNO, 1e-4f);
+ cosNI = max(cosNI, 1e-4f);
+
// eq. 9
float exp_arg = (dotx * dotx + doty * doty) / (dotn * dotn);
float denom = 4 * M_PI_F * m_ax * m_ay * oh * dotn * dotn * dotn;
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 817f254a5e5..585068ce8e2 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -326,7 +326,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __AO__
/* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion) {
+ if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
/* 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);
@@ -349,6 +349,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample,
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor;
+ ao_bsdf += shader_bsdf_ao(kg, &sd);
path_radiance_accum_ao(&L, throughput, ao_bsdf, ao_shadow, state.bounce);
}
}
@@ -503,7 +504,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
#ifdef __AO__
/* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion) {
+ if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
/* 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);
@@ -526,6 +527,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*kernel_data.background.ao_factor;
+ ao_bsdf += shader_bsdf_ao(kg, &sd);
path_radiance_accum_ao(L, throughput, ao_bsdf, ao_shadow, state.bounce);
}
}
@@ -706,7 +708,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
#ifdef __AO__
/* ambient occlusion */
- if(kernel_data.integrator.use_ambient_occlusion) {
+ if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
int num_samples = kernel_data.integrator.ao_samples;
float num_samples_inv = 1.0f/num_samples;
float ao_factor = kernel_data.background.ao_factor;
@@ -734,6 +736,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam
if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) {
float3 ao_bsdf = shader_bsdf_diffuse(kg, &sd)*ao_factor;
+ ao_bsdf += shader_bsdf_ao(kg, &sd);
path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce);
}
}
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 86886a6a231..1af5e048ad9 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -599,6 +599,27 @@ __device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd)
#endif
}
+__device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd)
+{
+#ifdef __MULTI_CLOSURE__
+ float3 eval = make_float3(0.0f, 0.0f, 0.0f);
+
+ for(int i = 0; i< sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type))
+ eval += sc->weight;
+ }
+
+ return eval;
+#else
+ if(CLOSURE_IS_AMBIENT_OCCLUSION(sd->closure.type))
+ return sd->closure.weight;
+ else
+ return make_float3(0.0f, 0.0f, 0.0f);
+#endif
+}
+
/* Emission */
__device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 98d998351a7..d4d88466688 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -393,16 +393,17 @@ enum ShaderDataFlag {
SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
SD_HOLDOUT = 32, /* have holdout closure? */
SD_VOLUME = 64, /* have volume closure? */
+ SD_AO = 128, /* have ao closure? */
/* shader flags */
- SD_SAMPLE_AS_LIGHT = 128, /* direct light sample */
- SD_HAS_SURFACE_TRANSPARENT = 256, /* has surface transparency */
- SD_HAS_VOLUME = 512, /* has volume shader */
- SD_HOMOGENEOUS_VOLUME = 1024, /* has homogeneous volume */
+ SD_SAMPLE_AS_LIGHT = 256, /* direct light sample */
+ SD_HAS_SURFACE_TRANSPARENT = 512, /* has surface transparency */
+ SD_HAS_VOLUME = 1024, /* has volume shader */
+ SD_HOMOGENEOUS_VOLUME = 2048, /* has homogeneous volume */
/* object flags */
- SD_HOLDOUT_MASK = 2048, /* holdout for camera rays */
- SD_OBJECT_MOTION = 4096 /* has object motion blur */
+ SD_HOLDOUT_MASK = 4096, /* holdout for camera rays */
+ SD_OBJECT_MOTION = 8192 /* has object motion blur */
};
typedef struct ShaderData {
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index b6e9473b7bf..eed4446cddc 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -73,6 +73,22 @@ public:
void print_on(std::ostream &out) const { out << name() << " ()"; }
};
+/// ambient occlusion closure
+///
+/// We only have a ambient occlusion closure for the shaders
+/// to return a color in ambient occlusion shaders. No methods,
+/// only the weight is taking into account
+///
+class AmbientOcclusionClosure : public ClosurePrimitive {
+public:
+ AmbientOcclusionClosure () : ClosurePrimitive((ClosurePrimitive::Category)AmbientOcclusion) {}
+
+ void setup() {};
+ size_t memsize() const { return sizeof(*this); }
+ const char *name() const { return "ambient_occlusion"; }
+ void print_on(std::ostream &out) const { out << name() << " ()"; }
+};
+
ClosureParam *closure_background_params()
{
static ClosureParam params[] = {
@@ -94,5 +110,16 @@ ClosureParam *closure_holdout_params()
CLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
+ClosureParam *closure_ambient_occlusion_params()
+{
+ static ClosureParam params[] = {
+ CLOSURE_STRING_KEYPARAM("label"),
+ CLOSURE_FINISH_PARAM(AmbientOcclusionClosure)
+ };
+ return params;
+}
+
+CLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 73e96643df7..de572d0e585 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -190,6 +190,8 @@ void OSLShader::register_closures(OSL::ShadingSystem *ss)
closure_background_params(), closure_background_prepare);
register_closure(ss, "holdout", id++,
closure_holdout_params(), closure_holdout_prepare);
+ register_closure(ss, "ambient_occlusion", id++,
+ closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index 574cb685db5..9137bad58d3 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -46,10 +46,16 @@ CCL_NAMESPACE_BEGIN
OSL::ClosureParam *closure_emission_params();
OSL::ClosureParam *closure_background_params();
OSL::ClosureParam *closure_holdout_params();
+OSL::ClosureParam *closure_ambient_occlusion_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
+void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data);
+
+enum {
+ AmbientOcclusion = 100
+};
#define CLOSURE_PREPARE(name, classname) \
void name(RendererServices *, int id, void *data) \
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 8b71ac30ab6..5d26f543efc 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -159,6 +159,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
sd->closure[sd->num_closure++] = sc;
break;
}
+ case AmbientOcclusion: {
+ if (sd->num_closure == MAX_CLOSURE)
+ return;
+
+ /* sample weight */
+ float sample_weight = fabsf(average(weight));
+
+ sc.sample_weight = sample_weight;
+ sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
+
+ sd->closure[sd->num_closure++] = sc;
+ sd->flag |= SD_AO;
+ break;
+ }
case OSL::ClosurePrimitive::Holdout:
if (sd->num_closure == MAX_CLOSURE)
return;
diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt
index 00ab52a1d13..4f5a97c1bb6 100644
--- a/intern/cycles/kernel/shaders/CMakeLists.txt
+++ b/intern/cycles/kernel/shaders/CMakeLists.txt
@@ -3,9 +3,11 @@
set(SRC_OSL
node_add_closure.osl
+ node_ambient_occlusion.osl
node_attribute.osl
node_background.osl
node_brick_texture.osl
+ node_brightness.osl
node_bump.osl
node_camera.osl
node_checker_texture.osl
@@ -21,35 +23,37 @@ set(SRC_OSL
node_environment_texture.osl
node_fresnel.osl
node_gamma.osl
- node_gradient_texture.osl
- node_brightness.osl
node_geometry.osl
node_glass_bsdf.osl
node_glossy_bsdf.osl
+ node_gradient_texture.osl
node_holdout.osl
node_hsv.osl
node_image_texture.osl
node_invert.osl
node_layer_weight.osl
- node_light_path.osl
node_light_falloff.osl
+ node_light_path.osl
node_magic_texture.osl
node_mapping.osl
node_math.osl
node_mix.osl
node_mix_closure.osl
node_musgrave_texture.osl
- node_normal.osl
node_noise_texture.osl
+ node_normal.osl
+ node_normal_map.osl
node_object_info.osl
node_output_displacement.osl
node_output_surface.osl
node_output_volume.osl
node_particle_info.osl
+ node_refraction_bsdf.osl
node_rgb_ramp.osl
node_separate_rgb.osl
node_set_normal.osl
node_sky_texture.osl
+ node_tangent.osl
node_texture_coordinate.osl
node_translucent_bsdf.osl
node_transparent_bsdf.osl
diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
new file mode 100644
index 00000000000..57a06f35461
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
@@ -0,0 +1,27 @@
+/*
+ * 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 "stdosl.h"
+
+shader node_ambient_occlusion(
+ color Color = color(0.8, 0.8, 0.8),
+ output closure color AO = ambient_occlusion())
+{
+ AO = Color * ambient_occlusion();
+}
+
diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl
index 953c5d1fa2b..3940b98eec1 100644
--- a/intern/cycles/kernel/shaders/node_geometry.osl
+++ b/intern/cycles/kernel/shaders/node_geometry.osl
@@ -47,26 +47,17 @@ shader node_geometry(
}
/* first try to get tangent attribute */
- vector T;
+ point generated;
- if (getattribute("geom:tangent", T)) {
- /* ensure orthogonal and normalized (interpolation breaks it) */
+ /* try to create spherical tangent from generated coordinates */
+ if (getattribute("geom:generated", generated)) {
+ vector T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
T = transform("object", "world", T);
Tangent = cross(Normal, normalize(cross(T, Normal)));
}
else {
- point generated;
-
- /* try to create spherical tangent from generated coordinates */
- if (getattribute("geom:generated", generated)) {
- T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
- T = transform("object", "world", T);
- Tangent = cross(Normal, normalize(cross(T, Normal)));
- }
- else {
- /* otherwise use surface derivatives */
- Tangent = normalize(dPdu);
- }
+ /* otherwise use surface derivatives */
+ Tangent = normalize(dPdu);
}
}
diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl
new file mode 100644
index 00000000000..e238313509e
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_normal_map.osl
@@ -0,0 +1,48 @@
+/*
+ * 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 "stdosl.h"
+
+shader node_normal_map(
+ normal NormalIn = N,
+ color Color = color(0.5, 0.5, 1.0),
+ string space = "Tangent",
+ string attr_name = "geom:tangent",
+ string attr_sign_name = "geom:tangent_sign",
+ output normal Normal = NormalIn)
+{
+ color mcolor = 2.0*color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
+
+ if (space == "Tangent") {
+ vector tangent;
+ float tangent_sign;
+
+ getattribute(attr_name, tangent);
+ getattribute(attr_sign_name, tangent_sign);
+
+ tangent = transform("object", "world", tangent);
+
+ vector B = tangent_sign * cross(NormalIn, tangent);
+ Normal = normalize(mcolor[0] * tangent + mcolor[1] * B + mcolor[2] * NormalIn);
+ }
+ else if (space == "Object")
+ Normal = normalize(transform("object", "world", vector(mcolor)));
+ else if (space == "World")
+ Normal = normalize(vector(mcolor));
+}
+
diff --git a/intern/cycles/kernel/shaders/node_refraction_bsdf.osl b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
new file mode 100644
index 00000000000..0cf9d460c6e
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_refraction_bsdf.osl
@@ -0,0 +1,39 @@
+/*
+ * 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 "stdosl.h"
+
+shader node_refraction_bsdf(
+ color Color = color(0.8, 0.8, 0.8),
+ string distribution = "Sharp",
+ float Roughness = 0.2,
+ float IOR = 1.45,
+ normal Normal = N,
+ output closure color BSDF = diffuse(Normal))
+{
+ float f = max(IOR, 1.0 + 1e-5);
+ float eta = backfacing() ? 1.0 / f: f;
+
+ if (distribution == "Sharp")
+ BSDF = Color * refraction(Normal, eta);
+ else if (distribution == "Beckmann")
+ BSDF = Color * microfacet_beckmann_refraction(Normal, Roughness, eta);
+ else if (distribution == "GGX")
+ BSDF = Color * microfacet_ggx_refraction(Normal, Roughness, eta);
+}
+
diff --git a/intern/cycles/kernel/shaders/node_tangent.osl b/intern/cycles/kernel/shaders/node_tangent.osl
new file mode 100644
index 00000000000..731af89231a
--- /dev/null
+++ b/intern/cycles/kernel/shaders/node_tangent.osl
@@ -0,0 +1,50 @@
+/*
+ * 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 "stdosl.h"
+
+shader node_tangent(
+ normal NormalIn = N,
+ string attr_name = "geom:tangent",
+ string direction_type = "Radial",
+ string axis = "Z",
+ output normal Tangent = normalize(dPdu))
+{
+ vector T;
+
+ if (direction_type == "UV Map") {
+ getattribute(attr_name, T);
+ }
+ else if (direction_type == "Radial") {
+ point generated;
+
+ if (!getattribute("geom:generated", generated))
+ generated = P;
+
+ if (axis == "X")
+ T = vector(0.0, -(generated[2] - 0.5), (generated[1] - 0.5));
+ else if (axis == "Y")
+ T = vector(-(generated[2] - 0.5), 0.0, (generated[0] - 0.5));
+ else
+ T = vector(-(generated[1] - 0.5), (generated[0] - 0.5), 0.0);
+ }
+
+ T = transform("object", "world", T);
+ Tangent = cross(NormalIn, normalize(cross(T, NormalIn)));
+}
+
diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl
index 03a0477038e..e5c6f0ad705 100644
--- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl
+++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl
@@ -38,12 +38,12 @@ shader node_ward_bsdf(
float aniso = clamp(Anisotropy, -0.99, 0.99);
if(aniso < 0.0) {
- RoughnessU = Roughness*(1.0 + aniso);
- RoughnessV = Roughness/(1.0 + aniso);
+ RoughnessU = Roughness/(1.0 + aniso);
+ RoughnessV = Roughness*(1.0 + aniso);
}
else {
- RoughnessU = Roughness/(1.0 - aniso);
- RoughnessV = Roughness*(1.0 - aniso);
+ RoughnessU = Roughness*(1.0 - aniso);
+ RoughnessV = Roughness/(1.0 - aniso);
}
BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV);
diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h
index 4237291c7a4..c55def2b47a 100644
--- a/intern/cycles/kernel/shaders/stdosl.h
+++ b/intern/cycles/kernel/shaders/stdosl.h
@@ -446,6 +446,7 @@ closure color ashikhmin_velvet(normal N, float sigma) BUILTIN;
closure color emission() BUILTIN;
closure color background() BUILTIN;
closure color holdout() BUILTIN;
+closure color ambient_occlusion() BUILTIN;
// Renderer state
int raytype (string typename) BUILTIN;
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 698ef5016f0..886fce63fd4 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -215,6 +215,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_CLOSURE_HOLDOUT:
svm_node_closure_holdout(sd, stack, node);
break;
+ case NODE_CLOSURE_AMBIENT_OCCLUSION:
+ svm_node_closure_ambient_occlusion(sd, stack, node);
+ break;
case NODE_CLOSURE_VOLUME:
svm_node_closure_volume(kg, sd, stack, node, path_flag);
break;
@@ -398,6 +401,12 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_LIGHT_FALLOFF:
svm_node_light_falloff(sd, stack, node);
break;
+ case NODE_TANGENT:
+ svm_node_tangent(kg, sd, stack, node);
+ break;
+ case NODE_NORMAL_MAP:
+ svm_node_normal_map(kg, sd, stack, node);
+ break;
#endif
case NODE_END:
default:
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 11ce3b7c5d1..f378d24463d 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -20,9 +20,9 @@ CCL_NAMESPACE_BEGIN
/* Closure Nodes */
-__device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
+__device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract)
{
- if(type == CLOSURE_BSDF_REFRACTION_ID) {
+ if(type == CLOSURE_BSDF_SHARP_GLASS_ID) {
if(refract) {
sc->data0 = eta;
sd->flag |= bsdf_refraction_setup(sc);
@@ -30,7 +30,7 @@ __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type,
else
sd->flag |= bsdf_reflection_setup(sc);
}
- else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) {
+ else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
sc->data0 = roughness;
sc->data1 = eta;
@@ -159,6 +159,31 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ sc->N = N;
+ sc->data0 = param1;
+ svm_node_closure_set_mix_weight(sc, mix_weight);
+
+ float eta = fmaxf(param2, 1.0f + 1e-5f);
+ sc->data1 = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
+
+ /* setup bsdf */
+ if(type == CLOSURE_BSDF_REFRACTION_ID)
+ sd->flag |= bsdf_refraction_setup(sc);
+ else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
+ sd->flag |= bsdf_microfacet_beckmann_refraction_setup(sc);
+ else
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(sc);
+
+ break;
+ }
+ case CLOSURE_BSDF_SHARP_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID:
+ case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: {
+#ifdef __CAUSTICS_TRICKS__
+ if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE))
+ break;
+#endif
/* index of refraction */
float eta = fmaxf(param2, 1.0f + 1e-5f);
eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
@@ -177,7 +202,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
float sample_weight = sc->sample_weight;
svm_node_closure_set_mix_weight(sc, mix_weight*fresnel);
- svm_node_glossy_setup(sd, sc, type, eta, roughness, false);
+ svm_node_glass_setup(sd, sc, type, eta, roughness, false);
/* refraction */
sc = svm_node_closure_get(sd);
@@ -187,7 +212,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
sc->sample_weight = sample_weight;
svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel));
- svm_node_glossy_setup(sd, sc, type, eta, roughness, true);
+ svm_node_glass_setup(sd, sc, type, eta, roughness, true);
#else
ShaderClosure *sc = svm_node_closure_get(sd);
sc->N = N;
@@ -195,7 +220,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
bool refract = (randb > fresnel);
svm_node_closure_set_mix_weight(sc, mix_weight);
- svm_node_glossy_setup(sd, sc, type, eta, roughness, refract);
+ svm_node_glass_setup(sd, sc, type, eta, roughness, refract);
#endif
break;
@@ -222,12 +247,12 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
float anisotropy = clamp(param2, -0.99f, 0.99f);
if(anisotropy < 0.0f) {
- sc->data0 = roughness*(1.0f + anisotropy);
- sc->data1 = roughness/(1.0f + anisotropy);
+ sc->data0 = roughness/(1.0f + anisotropy);
+ sc->data1 = roughness*(1.0f + anisotropy);
}
else {
- sc->data0 = roughness/(1.0f - anisotropy);
- sc->data1 = roughness*(1.0f - anisotropy);
+ sc->data0 = roughness*(1.0f - anisotropy);
+ sc->data1 = roughness/(1.0f - anisotropy);
}
sd->flag |= bsdf_ward_setup(sc);
@@ -372,6 +397,34 @@ __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
sd->flag |= SD_HOLDOUT;
}
+__device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
+{
+#ifdef __MULTI_CLOSURE__
+ uint mix_weight_offset = node.y;
+
+ if(stack_valid(mix_weight_offset)) {
+ float mix_weight = stack_load_float(stack, mix_weight_offset);
+
+ if(mix_weight == 0.0f)
+ return;
+
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ sc->weight *= mix_weight;
+ sc->type = CLOSURE_AMBIENT_OCCLUSION_ID;
+ }
+ else {
+ ShaderClosure *sc = svm_node_closure_get(sd);
+ sc->type = CLOSURE_AMBIENT_OCCLUSION_ID;
+ }
+
+#else
+ ShaderClosure *sc = &sd->closure;
+ sc->type = CLOSURE_AMBIENT_OCCLUSION_ID;
+#endif
+
+ sd->flag |= SD_AO;
+}
+
/* Closure Nodes */
__device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index 8e772f849c7..68177493f4e 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -29,29 +29,18 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack,
case NODE_GEOM_N: data = sd->N; break;
#ifdef __DPDU__
case NODE_GEOM_T: {
- /* first try to get tangent attribute */
- int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_TANGENT): ATTR_STD_NOT_FOUND;
+ /* try to create spherical tangent from generated coordinates */
+ int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
if(attr_offset != ATTR_STD_NOT_FOUND) {
- /* ensure orthogonal and normalized (interpolation breaks it) */
- data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
+ data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
+ data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f);
object_normal_transform(kg, sd, &data);
data = cross(sd->N, normalize(cross(data, sd->N)));;
}
else {
- /* try to create spherical tangent from generated coordinates */
- int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
-
- if(attr_offset != ATTR_STD_NOT_FOUND) {
- data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
- data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f);
- object_normal_transform(kg, sd, &data);
- data = cross(sd->N, normalize(cross(data, sd->N)));;
- }
- else {
- /* otherwise use surface derivatives */
- data = normalize(sd->dPdu);
- }
+ /* otherwise use surface derivatives */
+ data = normalize(sd->dPdu);
}
break;
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index 6bd8f2ac69c..2f73f7b9d40 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -225,5 +225,91 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
#endif
}
+__device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+{
+ uint color_offset, normal_offset, space;
+ decode_node_uchar4(node.y, &color_offset, &normal_offset, &space, NULL);
+
+ float3 color = stack_load_float3(stack, color_offset);
+ color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
+
+ if(space == NODE_NORMAL_MAP_TANGENT) {
+ /* tangent space */
+ if(sd->object == ~0) {
+ stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
+ return;
+ }
+
+ /* first try to get tangent attribute */
+ int attr_offset = find_attribute(kg, sd, node.z);
+ int attr_sign_offset = find_attribute(kg, sd, node.w);
+
+ if(attr_offset == ATTR_STD_NOT_FOUND || attr_offset == ATTR_STD_NOT_FOUND) {
+ stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
+ return;
+ }
+
+ /* ensure orthogonal and normalized (interpolation breaks it) */
+ float3 tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
+ float sign = triangle_attribute_float(kg, sd, ATTR_ELEMENT_CORNER, attr_sign_offset, NULL, NULL);
+
+ object_normal_transform(kg, sd, &tangent);
+ tangent = cross(sd->N, normalize(cross(tangent, sd->N)));;
+
+ float3 B = sign * cross(sd->N, tangent);
+ float3 N = color.x * tangent + color.y * B + color.z * sd->N;
+
+ stack_store_float3(stack, normal_offset, normalize(N));
+ }
+ else {
+ /* object, world space */
+ float3 N = color;
+
+ if(space == NODE_NORMAL_MAP_OBJECT)
+ object_normal_transform(kg, sd, &N);
+
+ stack_store_float3(stack, normal_offset, normalize(N));
+ }
+}
+
+__device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
+{
+ uint tangent_offset, direction_type, axis;
+ decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL);
+
+ float3 tangent;
+
+ if(direction_type == NODE_TANGENT_UVMAP) {
+ /* UV map */
+ int attr_offset = find_attribute(kg, sd, node.z);
+
+ if(attr_offset == ATTR_STD_NOT_FOUND)
+ tangent = make_float3(0.0f, 0.0f, 0.0f);
+ else
+ tangent = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, attr_offset, NULL, NULL);
+ }
+ else {
+ /* radial */
+ int attr_offset = find_attribute(kg, sd, node.z);
+ float3 generated;
+
+ if(attr_offset == ATTR_STD_NOT_FOUND)
+ generated = sd->P;
+ else
+ generated = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
+
+ if(axis == NODE_TANGENT_AXIS_X)
+ tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
+ else if(axis == NODE_TANGENT_AXIS_Y)
+ tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
+ else
+ tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
+ }
+
+ object_normal_transform(kg, sd, &tangent);
+ tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
+ stack_store_float3(stack, tangent_offset, tangent);
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 77df373a159..54767f3c87f 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -94,6 +94,9 @@ typedef enum NodeType {
NODE_PARTICLE_INFO,
NODE_TEX_BRICK,
NODE_CLOSURE_SET_NORMAL,
+ NODE_CLOSURE_AMBIENT_OCCLUSION,
+ NODE_TANGENT,
+ NODE_NORMAL_MAP
} NodeType;
typedef enum NodeAttributeType {
@@ -279,6 +282,23 @@ typedef enum NodeBlendWeightType {
NODE_LAYER_WEIGHT_FACING
} NodeBlendWeightType;
+typedef enum NodeTangentDirectionType {
+ NODE_TANGENT_RADIAL,
+ NODE_TANGENT_UVMAP
+} NodeTangentDirectionType;
+
+typedef enum NodeTangentAxis {
+ NODE_TANGENT_AXIS_X,
+ NODE_TANGENT_AXIS_Y,
+ NODE_TANGENT_AXIS_Z
+} NodeTangentAxis;
+
+typedef enum NodeNormalMapSpace {
+ NODE_NORMAL_MAP_TANGENT,
+ NODE_NORMAL_MAP_OBJECT,
+ NODE_NORMAL_MAP_WORLD
+} NodeNormalMapSpace;
+
typedef enum ShaderType {
SHADER_TYPE_SURFACE,
SHADER_TYPE_VOLUME,
@@ -307,7 +327,9 @@ typedef enum ClosureType {
CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
- CLOSURE_BSDF_GLASS_ID,
+ CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
+ CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
+ CLOSURE_BSDF_SHARP_GLASS_ID,
CLOSURE_BSDF_TRANSPARENT_ID,
@@ -317,6 +339,7 @@ typedef enum ClosureType {
CLOSURE_BACKGROUND_ID,
CLOSURE_HOLDOUT_ID,
CLOSURE_SUBSURFACE_ID,
+ CLOSURE_AMBIENT_OCCLUSION_ID,
CLOSURE_VOLUME_ID,
CLOSURE_VOLUME_TRANSPARENT_ID,
@@ -329,11 +352,12 @@ typedef enum ClosureType {
#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_OREN_NAYAR_ID)
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_WESTIN_SHEEN_ID)
-#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_GLASS_ID)
+#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID)
#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
#define CLOSURE_IS_BACKGROUND(type) (type == CLOSURE_BACKGROUND_ID)
+#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
CCL_NAMESPACE_END