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:
-rw-r--r--intern/cycles/blender/blender_mesh.cpp106
-rw-r--r--intern/cycles/blender/blender_shader.cpp38
-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
-rw-r--r--intern/cycles/render/attribute.cpp4
-rw-r--r--intern/cycles/render/nodes.cpp264
-rw-r--r--intern/cycles/render/nodes.h38
-rw-r--r--intern/cycles/util/util_attribute.cpp4
-rw-r--r--intern/cycles/util/util_types.h3
-rw-r--r--source/blender/blenkernel/BKE_node.h4
-rw-r--r--source/blender/blenkernel/intern/node.c4
-rw-r--r--source/blender/editors/space_node/drawnode.c31
-rw-r--r--source/blender/makesdna/DNA_node_types.h25
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c61
-rw-r--r--source/blender/makesrna/intern/rna_nodetree_types.h6
-rw-r--r--source/blender/nodes/CMakeLists.txt28
-rw-r--r--source/blender/nodes/NOD_shader.h4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c63
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c68
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c69
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tangent.c60
40 files changed, 1280 insertions, 127 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 0e13479a761..69b330db483 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -116,7 +116,7 @@ static void mikk_set_tangent_space(const SMikkTSpaceContext *context, const floa
userdata->tangent[face*4 + vert] = make_float4(T[0], T[1], T[2], sign);
}
-static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts)
+static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_layer, Mesh *mesh, vector<int>& nverts, bool need_sign, bool active_render)
{
/* setup userdata */
MikkUserData userdata(b_mesh, b_layer, nverts.size());
@@ -140,22 +140,57 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la
/* compute tangents */
genTangSpaceDefault(&context);
- /* create attribute */
- /* todo: create float4 attribute for sign */
- Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("tangent"));
+ /* create tangent attributes */
+ Attribute *attr;
+ ustring name = ustring((string(b_layer.name().c_str()) + ".tangent").c_str());
+
+ if(active_render)
+ attr = mesh->attributes.add(ATTR_STD_UV_TANGENT, name);
+ else
+ attr = mesh->attributes.add(name, TypeDesc::TypeVector, Attribute::CORNER);
+
float3 *tangent = attr->data_float3();
- for (int i = 0; i < nverts.size(); i++) {
+ /* create bitangent sign attribute */
+ float *tangent_sign = NULL;
+
+ if(need_sign) {
+ Attribute *attr_sign;
+ ustring name_sign = ustring((string(b_layer.name().c_str()) + ".tangent_sign").c_str());
+
+ if(active_render)
+ attr_sign = mesh->attributes.add(ATTR_STD_UV_TANGENT_SIGN, name_sign);
+ else
+ attr_sign = mesh->attributes.add(name_sign, TypeDesc::TypeFloat, Attribute::CORNER);
+
+ tangent_sign = attr_sign->data_float();
+ }
+
+ for(int i = 0; i < nverts.size(); i++) {
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 1]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 2]);
tangent += 3;
+ if(tangent_sign) {
+ tangent_sign[0] = userdata.tangent[i*4 + 0].w;
+ tangent_sign[1] = userdata.tangent[i*4 + 1].w;
+ tangent_sign[2] = userdata.tangent[i*4 + 2].w;
+ tangent_sign += 3;
+ }
+
if(nverts[i] == 4) {
tangent[0] = float4_to_float3(userdata.tangent[i*4 + 0]);
tangent[1] = float4_to_float3(userdata.tangent[i*4 + 2]);
tangent[2] = float4_to_float3(userdata.tangent[i*4 + 3]);
tangent += 3;
+
+ if(tangent_sign) {
+ tangent_sign[0] = userdata.tangent[i*4 + 0].w;
+ tangent_sign[1] = userdata.tangent[i*4 + 2].w;
+ tangent_sign[2] = userdata.tangent[i*4 + 3].w;
+ tangent_sign += 3;
+ }
}
}
}
@@ -233,48 +268,49 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
BL::Mesh::tessface_uv_textures_iterator l;
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
- AttributeStandard std = (l->active_render())? ATTR_STD_UV: ATTR_STD_NONE;
+ bool active_render = l->active_render();
+ AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
ustring name = ustring(l->name().c_str());
- if(!(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)))
- continue;
+ /* UV map */
+ if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
+ Attribute *attr;
- Attribute *attr;
-
- if(l->active_render())
- attr = mesh->attributes.add(std, name);
- else
- attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
-
- BL::MeshTextureFaceLayer::data_iterator t;
- float3 *fdata = attr->data_float3();
- size_t i = 0;
+ if(active_render)
+ attr = mesh->attributes.add(std, name);
+ else
+ attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);
- for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
- fdata[0] = get_float3(t->uv1());
- fdata[1] = get_float3(t->uv2());
- fdata[2] = get_float3(t->uv3());
- fdata += 3;
+ BL::MeshTextureFaceLayer::data_iterator t;
+ float3 *fdata = attr->data_float3();
+ size_t i = 0;
- if(nverts[i] == 4) {
+ for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
fdata[0] = get_float3(t->uv1());
- fdata[1] = get_float3(t->uv3());
- fdata[2] = get_float3(t->uv4());
+ fdata[1] = get_float3(t->uv2());
+ fdata[2] = get_float3(t->uv3());
fdata += 3;
+
+ if(nverts[i] == 4) {
+ fdata[0] = get_float3(t->uv1());
+ fdata[1] = get_float3(t->uv3());
+ fdata[2] = get_float3(t->uv4());
+ fdata += 3;
+ }
}
}
- }
- }
- /* create texcoord-based tangent attributes */
- if(mesh->need_attribute(scene, ATTR_STD_TANGENT)) {
- BL::Mesh::tessface_uv_textures_iterator l;
+ /* UV tangent */
+ std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
+ name = ustring((string(name.c_str()) + ".tangent").c_str());
- for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
- if(!l->active_render())
- continue;
+ if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
+ std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
+ name = ustring((string(name.c_str()) + ".tangent_sign").c_str());
+ bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));
- mikk_compute_tangents(b_mesh, *l, mesh, nverts);
+ mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render);
+ }
}
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 1f8d86a7f70..6dc0bbdb90e 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -173,6 +173,7 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
case BL::ShaderNode::type_OUTPUT: break;
case BL::ShaderNode::type_SQUEEZE: break;
case BL::ShaderNode::type_TEXTURE: break;
+ case BL::ShaderNode::type_FRAME: break;
/* handled outside this function */
case BL::ShaderNode::type_GROUP: break;
/* existing blender nodes */
@@ -366,6 +367,23 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = glass;
break;
}
+ case BL::ShaderNode::type_BSDF_REFRACTION: {
+ BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
+ RefractionBsdfNode *refraction = new RefractionBsdfNode();
+ switch(b_refraction_node.distribution()) {
+ case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
+ refraction->distribution = ustring("Sharp");
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
+ refraction->distribution = ustring("Beckmann");
+ break;
+ case BL::ShaderNodeBsdfRefraction::distribution_GGX:
+ refraction->distribution = ustring("GGX");
+ break;
+ }
+ node = refraction;
+ break;
+ }
case BL::ShaderNode::type_BSDF_TRANSLUCENT: {
node = new TranslucentBsdfNode();
break;
@@ -382,6 +400,10 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = new EmissionNode();
break;
}
+ case BL::ShaderNode::type_AMBIENT_OCCLUSION: {
+ node = new AmbientOcclusionNode();
+ break;
+ }
case BL::ShaderNode::type_VOLUME_ISOTROPIC: {
node = new IsotropicVolumeNode();
break;
@@ -573,7 +595,21 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen
node = sky;
break;
}
- case BL::ShaderNode::type_FRAME: {
+ case BL::ShaderNode::type_NORMAL_MAP: {
+ BL::ShaderNodeNormalMap b_normal_map_node(b_node);
+ NormalMapNode *nmap = new NormalMapNode();
+ nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
+ nmap->attribute = b_normal_map_node.uv_map();
+ node = nmap;
+ break;
+ }
+ case BL::ShaderNode::type_TANGENT: {
+ BL::ShaderNodeTangent b_tangent_node(b_node);
+ TangentNode *tangent = new TangentNode();
+ tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
+ tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
+ tangent->attribute = b_tangent_node.uv_map();
+ node = tangent;
break;
}
}
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
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index c7a9ab3e51a..95941c14b6c 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -162,8 +162,10 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
else if(std == ATTR_STD_UV)
attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
- else if(std == ATTR_STD_TANGENT)
+ else if(std == ATTR_STD_UV_TANGENT)
attr = add(name, TypeDesc::TypeVector, Attribute::CORNER);
+ else if(std == ATTR_STD_UV_TANGENT_SIGN)
+ attr = add(name, TypeDesc::TypeFloat, Attribute::CORNER);
else if(std == ATTR_STD_GENERATED)
attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
else if(std == ATTR_STD_POSITION_UNDEFORMED)
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index d7bf71337f6..4f50de11edf 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1284,10 +1284,8 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes)
{
ShaderInput *tangent_in = input("Tangent");
- if(!tangent_in->link) {
- attributes->add(ATTR_STD_TANGENT);
+ if(!tangent_in->link)
attributes->add(ATTR_STD_GENERATED);
- }
ShaderNode::attributes(attributes);
}
@@ -1346,9 +1344,9 @@ static ShaderEnum glass_distribution_init()
{
ShaderEnum enm;
- enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID);
- enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
- enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+ enm.insert("Sharp", CLOSURE_BSDF_SHARP_GLASS_ID);
+ enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID);
+ enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
return enm;
}
@@ -1367,7 +1365,7 @@ void GlassBsdfNode::compile(SVMCompiler& compiler)
{
closure = (ClosureType)distribution_enum[distribution];
- if(closure == CLOSURE_BSDF_REFRACTION_ID)
+ if(closure == CLOSURE_BSDF_SHARP_GLASS_ID)
BsdfNode::compile(compiler, NULL, input("IOR"));
else
BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
@@ -1379,6 +1377,45 @@ void GlassBsdfNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_glass_bsdf");
}
+/* Refraction BSDF Closure */
+
+static ShaderEnum refraction_distribution_init()
+{
+ ShaderEnum enm;
+
+ enm.insert("Sharp", CLOSURE_BSDF_REFRACTION_ID);
+ enm.insert("Beckmann", CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID);
+ enm.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID);
+
+ return enm;
+}
+
+ShaderEnum RefractionBsdfNode::distribution_enum = refraction_distribution_init();
+
+RefractionBsdfNode::RefractionBsdfNode()
+{
+ distribution = ustring("Sharp");
+
+ add_input("Roughness", SHADER_SOCKET_FLOAT, 0.0f);
+ add_input("IOR", SHADER_SOCKET_FLOAT, 0.3f);
+}
+
+void RefractionBsdfNode::compile(SVMCompiler& compiler)
+{
+ closure = (ClosureType)distribution_enum[distribution];
+
+ if(closure == CLOSURE_BSDF_REFRACTION_ID)
+ BsdfNode::compile(compiler, NULL, input("IOR"));
+ else
+ BsdfNode::compile(compiler, input("Roughness"), input("IOR"));
+}
+
+void RefractionBsdfNode::compile(OSLCompiler& compiler)
+{
+ compiler.parameter("distribution", distribution);
+ compiler.add(this, "node_refraction_bsdf");
+}
+
/* Velvet BSDF Closure */
VelvetBsdfNode::VelvetBsdfNode()
@@ -1536,6 +1573,34 @@ void HoldoutNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_holdout");
}
+/* Ambient Occlusion */
+
+AmbientOcclusionNode::AmbientOcclusionNode()
+: ShaderNode("ambient_occlusion")
+{
+ add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f));
+ add_output("AO", SHADER_SOCKET_CLOSURE);
+}
+
+void AmbientOcclusionNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *color_in = input("Color");
+
+ if(color_in->link) {
+ compiler.stack_assign(color_in);
+ compiler.add_node(NODE_CLOSURE_WEIGHT, color_in->stack_offset);
+ }
+ else
+ compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color_in->value);
+
+ compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset());
+}
+
+void AmbientOcclusionNode::compile(OSLCompiler& compiler)
+{
+ compiler.add(this, "node_ambient_occlusion");
+}
+
/* Volume Closure */
VolumeNode::VolumeNode()
@@ -1635,10 +1700,8 @@ GeometryNode::GeometryNode()
void GeometryNode::attributes(AttributeRequestSet *attributes)
{
- if(!output("Tangent")->links.empty()) {
- attributes->add(ATTR_STD_TANGENT);
+ if(!output("Tangent")->links.empty())
attributes->add(ATTR_STD_GENERATED);
- }
ShaderNode::attributes(attributes);
}
@@ -2075,13 +2138,14 @@ void ParticleInfoNode::compile(SVMCompiler& compiler)
compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_LOCATION, out->stack_offset);
}
- #if 0 /* XXX Quaternion data is not yet supported by Cycles */
+ /* quaternion data is not yet supported by Cycles */
+#if 0
out = output("Rotation");
if(!out->links.empty()) {
compiler.stack_assign(out);
compiler.add_node(NODE_PARTICLE_INFO, NODE_INFO_PAR_ROTATION, out->stack_offset);
}
- #endif
+#endif
out = output("Size");
if(!out->links.empty()) {
@@ -2946,5 +3010,181 @@ void OSLScriptNode::compile(OSLCompiler& compiler)
compiler.add(this, bytecode_hash.c_str(), false);
}
+/* Normal Map */
+
+static ShaderEnum normal_map_space_init()
+{
+ ShaderEnum enm;
+
+ enm.insert("Tangent", NODE_NORMAL_MAP_TANGENT);
+ enm.insert("Object", NODE_NORMAL_MAP_OBJECT);
+ enm.insert("World", NODE_NORMAL_MAP_WORLD);
+
+ return enm;
+}
+
+ShaderEnum NormalMapNode::space_enum = normal_map_space_init();
+
+NormalMapNode::NormalMapNode()
+: ShaderNode("normal_map")
+{
+ space = ustring("Tangent");
+ attribute = ustring("");
+
+ add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
+ add_input("Color", SHADER_SOCKET_COLOR);
+ add_output("Normal", SHADER_SOCKET_NORMAL);
+}
+
+void NormalMapNode::attributes(AttributeRequestSet *attributes)
+{
+ if(space == ustring("Tangent")) {
+ if(attribute == ustring("")) {
+ attributes->add(ATTR_STD_UV_TANGENT);
+ attributes->add(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ ShaderNode::attributes(attributes);
+}
+
+void NormalMapNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *color_in = input("Color");
+ ShaderOutput *normal_out = output("Normal");
+ int attr = 0, attr_sign = 0;
+
+ if(space == ustring("Tangent")) {
+ if(attribute == ustring("")) {
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ attr_sign = compiler.attribute(ATTR_STD_UV_TANGENT_SIGN);
+ }
+ else {
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ attr_sign = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.stack_assign(color_in);
+ compiler.stack_assign(normal_out);
+
+ compiler.add_node(NODE_NORMAL_MAP,
+ compiler.encode_uchar4(
+ color_in->stack_offset,
+ normal_out->stack_offset,
+ space_enum[space]),
+ attr, attr_sign);
+}
+
+void NormalMapNode::compile(OSLCompiler& compiler)
+{
+ if(space == ustring("Tangent")) {
+ if(attribute == ustring("")) {
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ compiler.parameter("attr_sign_name", ustring("geom:tangent_sign"));
+ }
+ else {
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ compiler.parameter("attr_sign_name", ustring((string(attribute.c_str()) + ".tangent_sign").c_str()));
+ }
+ }
+
+ compiler.parameter("space", space);
+
+ compiler.add(this, "node_normal_map");
+}
+
+/* Tangent */
+
+static ShaderEnum tangent_direction_type_init()
+{
+ ShaderEnum enm;
+
+ enm.insert("Radial", NODE_TANGENT_RADIAL);
+ enm.insert("UV Map", NODE_TANGENT_UVMAP);
+
+ return enm;
+}
+
+static ShaderEnum tangent_axis_init()
+{
+ ShaderEnum enm;
+
+ enm.insert("X", NODE_TANGENT_AXIS_X);
+ enm.insert("Y", NODE_TANGENT_AXIS_Y);
+ enm.insert("Z", NODE_TANGENT_AXIS_Z);
+
+ return enm;
+}
+
+ShaderEnum TangentNode::direction_type_enum = tangent_direction_type_init();
+ShaderEnum TangentNode::axis_enum = tangent_axis_init();
+
+TangentNode::TangentNode()
+: ShaderNode("normal_map")
+{
+ direction_type = ustring("Radial");
+ axis = ustring("X");
+ attribute = ustring("");
+
+ add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true);
+ add_output("Tangent", SHADER_SOCKET_NORMAL);
+}
+
+void TangentNode::attributes(AttributeRequestSet *attributes)
+{
+ if(direction_type == ustring("UV Map")) {
+ if(attribute == ustring(""))
+ attributes->add(ATTR_STD_UV_TANGENT);
+ else
+ attributes->add(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
+ else
+ attributes->add(ATTR_STD_GENERATED);
+
+ ShaderNode::attributes(attributes);
+}
+
+void TangentNode::compile(SVMCompiler& compiler)
+{
+ ShaderOutput *tangent_out = output("Tangent");
+ int attr;
+
+ if(direction_type == ustring("UV Map")) {
+ if(attribute == ustring(""))
+ attr = compiler.attribute(ATTR_STD_UV_TANGENT);
+ else
+ attr = compiler.attribute(ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
+ else
+ attr = compiler.attribute(ATTR_STD_GENERATED);
+
+ compiler.stack_assign(tangent_out);
+
+ compiler.add_node(NODE_TANGENT,
+ compiler.encode_uchar4(
+ tangent_out->stack_offset,
+ direction_type_enum[direction_type],
+ axis_enum[axis]), attr);
+}
+
+void TangentNode::compile(OSLCompiler& compiler)
+{
+ if(direction_type == ustring("UV Map")) {
+ if(attribute == ustring(""))
+ compiler.parameter("attr_name", ustring("geom:tangent"));
+ else
+ compiler.parameter("attr_name", ustring((string(attribute.c_str()) + ".tangent").c_str()));
+ }
+
+ compiler.parameter("direction_type", direction_type);
+ compiler.parameter("axis", axis);
+ compiler.add(this, "node_tangent");
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index d90cae5f668..27b07769e28 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -240,6 +240,14 @@ public:
static ShaderEnum distribution_enum;
};
+class RefractionBsdfNode : public BsdfNode {
+public:
+ SHADER_NODE_CLASS(RefractionBsdfNode)
+
+ ustring distribution;
+ static ShaderEnum distribution_enum;
+};
+
class EmissionNode : public ShaderNode {
public:
SHADER_NODE_CLASS(EmissionNode)
@@ -257,6 +265,11 @@ public:
SHADER_NODE_CLASS(HoldoutNode)
};
+class AmbientOcclusionNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(AmbientOcclusionNode)
+};
+
class VolumeNode : public ShaderNode {
public:
SHADER_NODE_CLASS(VolumeNode)
@@ -457,6 +470,31 @@ public:
vector<ustring> output_names;
};
+class NormalMapNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(NormalMapNode)
+ void attributes(AttributeRequestSet *attributes);
+
+ ustring space;
+ static ShaderEnum space_enum;
+
+ ustring attribute;
+};
+
+class TangentNode : public ShaderNode {
+public:
+ SHADER_NODE_CLASS(TangentNode)
+ void attributes(AttributeRequestSet *attributes);
+
+ ustring direction_type;
+ static ShaderEnum direction_type_enum;
+
+ ustring axis;
+ static ShaderEnum axis_enum;
+
+ ustring attribute;
+};
+
CCL_NAMESPACE_END
#endif /* __NODES_H__ */
diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp
index 163a92902f3..057fb6213e9 100644
--- a/intern/cycles/util/util_attribute.cpp
+++ b/intern/cycles/util/util_attribute.cpp
@@ -30,8 +30,10 @@ const char *attribute_standard_name(AttributeStandard std)
return "uv";
else if(std == ATTR_STD_GENERATED)
return "generated";
- else if(std == ATTR_STD_TANGENT)
+ else if(std == ATTR_STD_UV_TANGENT)
return "tangent";
+ else if(std == ATTR_STD_UV_TANGENT_SIGN)
+ return "tangent_sign";
else if(std == ATTR_STD_POSITION_UNDEFORMED)
return "undeformed";
else if(std == ATTR_STD_POSITION_UNDISPLACED)
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index f2c02cadcbf..fe530d727ad 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -449,7 +449,8 @@ typedef enum AttributeStandard {
ATTR_STD_VERTEX_NORMAL,
ATTR_STD_FACE_NORMAL,
ATTR_STD_UV,
- ATTR_STD_TANGENT,
+ ATTR_STD_UV_TANGENT,
+ ATTR_STD_UV_TANGENT_SIGN,
ATTR_STD_GENERATED,
ATTR_STD_POSITION_UNDEFORMED,
ATTR_STD_POSITION_UNDISPLACED,
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 29e03f66bcc..b365d93b246 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -553,6 +553,10 @@ struct ShadeResult;
#define SH_NODE_TEX_BRICK 169
#define SH_NODE_BUMP 170
#define SH_NODE_SCRIPT 171
+#define SH_NODE_AMBIENT_OCCLUSION 172
+#define SH_NODE_BSDF_REFRACTION 173
+#define SH_NODE_TANGENT 174
+#define SH_NODE_NORMAL_MAP 175
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 153eb5271c5..2d76484b60a 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -2293,17 +2293,21 @@ static void registerShaderNodes(bNodeTreeType *ttype)
register_node_type_sh_particle_info(ttype);
register_node_type_sh_bump(ttype);
register_node_type_sh_script(ttype);
+ register_node_type_sh_tangent(ttype);
+ register_node_type_sh_normal_map(ttype);
register_node_type_sh_background(ttype);
register_node_type_sh_bsdf_anisotropic(ttype);
register_node_type_sh_bsdf_diffuse(ttype);
register_node_type_sh_bsdf_glossy(ttype);
register_node_type_sh_bsdf_glass(ttype);
+ register_node_type_sh_bsdf_refraction(ttype);
register_node_type_sh_bsdf_translucent(ttype);
register_node_type_sh_bsdf_transparent(ttype);
register_node_type_sh_bsdf_velvet(ttype);
register_node_type_sh_emission(ttype);
register_node_type_sh_holdout(ttype);
+ register_node_type_sh_ambient_occlusion(ttype);
//register_node_type_sh_volume_transparent(ttype);
//register_node_type_sh_volume_isotropic(ttype);
register_node_type_sh_mix_shader(ttype);
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 0938562857b..b99842502ec 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -1379,6 +1379,30 @@ static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), Po
uiItemR(layout, ptr, "from_dupli", 0, NULL, 0);
}
+static void node_shader_buts_normal_map(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "space", 0, "", 0);
+
+ if(RNA_enum_get(ptr, "space") == SHD_NORMAL_MAP_TANGENT)
+ uiItemR(layout, ptr, "uv_map", 0, NULL, 0);
+}
+
+static void node_shader_buts_tangent(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiLayout *split, *row;
+
+ split = uiLayoutSplit(layout, 0.0f, FALSE);
+
+ uiItemR(split, ptr, "direction_type", 0, "", 0);
+
+ row = uiLayoutRow(split, FALSE);
+
+ if(RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP)
+ uiItemR(row, ptr, "uv_map", 0, "", 0);
+ else
+ uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0);
+}
+
static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
@@ -1491,8 +1515,15 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_TEX_COORD:
ntype->uifunc = node_shader_buts_tex_coord;
break;
+ case SH_NODE_NORMAL_MAP:
+ ntype->uifunc = node_shader_buts_normal_map;
+ break;
+ case SH_NODE_TANGENT:
+ ntype->uifunc = node_shader_buts_tangent;
+ break;
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_GLASS:
+ case SH_NODE_BSDF_REFRACTION:
ntype->uifunc = node_shader_buts_glossy;
break;
case SH_NODE_SCRIPT:
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index c73ba87754f..3437e6dfcf1 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -716,6 +716,17 @@ typedef struct NodeShaderScript {
IDProperty *prop;
} NodeShaderScript;
+typedef struct NodeShaderTangent {
+ int direction_type;
+ int axis;
+ char uv_map[64];
+} NodeShaderTangent;
+
+typedef struct NodeShaderNormalMap {
+ int space;
+ char uv_map[64];
+} NodeShaderNormalMap;
+
/* script node mode */
#define NODE_SCRIPT_INTERNAL 0
#define NODE_SCRIPT_EXTERNAL 1
@@ -800,6 +811,20 @@ typedef struct NodeShaderScript {
#define SHD_PROJ_FLAT 0
#define SHD_PROJ_BOX 1
+/* tangent */
+#define SHD_TANGENT_RADIAL 0
+#define SHD_TANGENT_UVMAP 1
+
+/* tangent */
+#define SHD_TANGENT_AXIS_X 0
+#define SHD_TANGENT_AXIS_Y 1
+#define SHD_TANGENT_AXIS_Z 2
+
+/* normal map space */
+#define SHD_NORMAL_MAP_TANGENT 0
+#define SHD_NORMAL_MAP_OBJECT 1
+#define SHD_NORMAL_MAP_WORLD 2
+
/* blur node */
#define CMP_NODE_BLUR_ASPECT_NONE 0
#define CMP_NODE_BLUR_ASPECT_Y 1
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 312469340a7..93f37682aa3 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1850,6 +1850,67 @@ static void def_glossy(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
+static void def_sh_normal_map(StructRNA *srna)
+{
+ static EnumPropertyItem prop_space_items[] = {
+ {SHD_NORMAL_MAP_TANGENT, "TANGENT", 0, "Tangent Space", "Tangent space normal mapping"},
+ {SHD_NORMAL_MAP_OBJECT, "OBJECT", 0, "Object Space", "Object space normal mapping"},
+ {SHD_NORMAL_MAP_WORLD, "WORLD", 0, "World Space", "World space normal mapping"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeShaderNormalMap", "storage");
+
+ prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_space_items);
+ RNA_def_property_ui_text(prop, "Space", "Space of the input normal");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "UV Map", "Name of the UV Map for for tangent space maps");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "bNode", NULL);
+}
+
+static void def_sh_tangent(StructRNA *srna)
+{
+ static EnumPropertyItem prop_direction_type_items[] = {
+ {SHD_TANGENT_RADIAL, "RADIAL", 0, "Radial", "Radial tangent around the X, Y or Z axis"},
+ {SHD_TANGENT_UVMAP, "UV_MAP", 0, "UV Map", "Tangent from UV map"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static EnumPropertyItem prop_axis_items[] = {
+ {SHD_TANGENT_AXIS_X, "X", 0, "X", "X axis"},
+ {SHD_TANGENT_AXIS_Y, "Y", 0, "Y", "Y axis"},
+ {SHD_TANGENT_AXIS_Z, "Z", 0, "Z", "Z axis"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ PropertyRNA *prop;
+
+ RNA_def_struct_sdna_from(srna, "NodeShaderTangent", "storage");
+
+ prop = RNA_def_property(srna, "direction_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_direction_type_items);
+ RNA_def_property_ui_text(prop, "Direction", "Method to use for the tangent");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, prop_axis_items);
+ RNA_def_property_ui_text(prop, "Axis", "Axis for radial tangents");
+ RNA_def_property_update(prop, 0, "rna_Node_update");
+
+ prop = RNA_def_property(srna, "uv_map", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "UV Map", "Name of the UV Map for for tangent generated from UV");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+ RNA_def_struct_sdna_from(srna, "bNode", NULL);
+}
+
static void def_sh_script(StructRNA *srna)
{
FunctionRNA *func;
diff --git a/source/blender/makesrna/intern/rna_nodetree_types.h b/source/blender/makesrna/intern/rna_nodetree_types.h
index c45c9b71442..fbbcbae6c12 100644
--- a/source/blender/makesrna/intern/rna_nodetree_types.h
+++ b/source/blender/makesrna/intern/rna_nodetree_types.h
@@ -65,12 +65,14 @@ DefNode( ShaderNode, SH_NODE_LAYER_WEIGHT, 0, "LA
DefNode( ShaderNode, SH_NODE_MIX_SHADER, 0, "MIX_SHADER", MixShader, "Mix Shader", "" )
DefNode( ShaderNode, SH_NODE_ADD_SHADER, 0, "ADD_SHADER", AddShader, "Add Shader", "" )
DefNode( ShaderNode, SH_NODE_ATTRIBUTE, def_sh_attribute, "ATTRIBUTE", Attribute, "Attribute", "" )
+DefNode( ShaderNode, SH_NODE_AMBIENT_OCCLUSION, 0, "AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", "" )
DefNode( ShaderNode, SH_NODE_BACKGROUND, 0, "BACKGROUND", Background, "Background", "" )
DefNode( ShaderNode, SH_NODE_HOLDOUT, 0, "HOLDOUT", Holdout, "Holdout", "" )
DefNode( ShaderNode, SH_NODE_BSDF_ANISOTROPIC, 0, "BSDF_ANISOTROPIC", BsdfAnisotropic, "Anisotropic Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_DIFFUSE, 0, "BSDF_DIFFUSE", BsdfDiffuse, "Diffuse Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLOSSY, def_glossy, "BSDF_GLOSSY", BsdfGlossy, "Glossy Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_GLASS, def_glossy, "BSDF_GLASS", BsdfGlass, "Glass Bsdf", "" )
+DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BSDF_REFRACTION", BsdfRefraction, "Refraction Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent Bsdf", "" )
DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet Bsdf", "" )
@@ -82,7 +84,9 @@ DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LI
DefNode( ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIGHT_FALLOFF", LightFalloff, "Light Falloff", "" )
DefNode( ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" )
DefNode( ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" )
-DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", BumpNode, "Bump", "" )
+DefNode( ShaderNode, SH_NODE_BUMP, 0, "BUMP", Bump, "Bump", "" )
+DefNode( ShaderNode, SH_NODE_NORMAL_MAP, def_sh_normal_map, "NORMAL_MAP", NormalMap, "Normal Map", "" )
+DefNode( ShaderNode, SH_NODE_TANGENT, def_sh_tangent, "TANGENT", Tangent, "Tangent", "" )
DefNode( ShaderNode, SH_NODE_SCRIPT, def_sh_script, "SCRIPT", Script, "Script", "" )
DefNode( ShaderNode, SH_NODE_TEX_IMAGE, def_sh_tex_image, "TEX_IMAGE", TexImage, "Image Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_ENVIRONMENT, def_sh_tex_environment, "TEX_ENVIRONMENT", TexEnvironment, "Environment Texture","" )
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 323a534c989..7dca4d07b24 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -145,36 +145,40 @@ set(SRC
shader/nodes/node_shader_valToRgb.c
shader/nodes/node_shader_value.c
shader/nodes/node_shader_vectMath.c
+ shader/nodes/node_shader_add_shader.c
+ shader/nodes/node_shader_ambient_occlusion.c
shader/nodes/node_shader_attribute.c
shader/nodes/node_shader_background.c
shader/nodes/node_shader_bsdf_anisotropic.c
shader/nodes/node_shader_bsdf_diffuse.c
- shader/nodes/node_shader_bsdf_glossy.c
shader/nodes/node_shader_bsdf_glass.c
+ shader/nodes/node_shader_bsdf_glossy.c
+ shader/nodes/node_shader_bsdf_refraction.c
shader/nodes/node_shader_bsdf_translucent.c
shader/nodes/node_shader_bsdf_transparent.c
shader/nodes/node_shader_bsdf_velvet.c
shader/nodes/node_shader_bump.c
shader/nodes/node_shader_emission.c
shader/nodes/node_shader_fresnel.c
- shader/nodes/node_shader_layer_weight.c
shader/nodes/node_shader_geometry.c
shader/nodes/node_shader_holdout.c
- shader/nodes/node_shader_volume_transparent.c
- shader/nodes/node_shader_volume_isotropic.c
- shader/nodes/node_shader_light_path.c
+ shader/nodes/node_shader_layer_weight.c
shader/nodes/node_shader_light_falloff.c
- shader/nodes/node_shader_object_info.c
- shader/nodes/node_shader_script.c
- shader/nodes/node_shader_particle_info.c
+ shader/nodes/node_shader_light_path.c
shader/nodes/node_shader_mix_shader.c
- shader/nodes/node_shader_add_shader.c
+ shader/nodes/node_shader_normal_map.c
+ shader/nodes/node_shader_object_info.c
shader/nodes/node_shader_output_lamp.c
shader/nodes/node_shader_output_material.c
shader/nodes/node_shader_output_world.c
- shader/nodes/node_shader_tex_gradient.c
+ shader/nodes/node_shader_particle_info.c
+ shader/nodes/node_shader_script.c
+ shader/nodes/node_shader_tangent.c
+ shader/nodes/node_shader_tex_brick.c
+ shader/nodes/node_shader_tex_checker.c
shader/nodes/node_shader_tex_coord.c
shader/nodes/node_shader_tex_environment.c
+ shader/nodes/node_shader_tex_gradient.c
shader/nodes/node_shader_tex_image.c
shader/nodes/node_shader_tex_magic.c
shader/nodes/node_shader_tex_musgrave.c
@@ -182,8 +186,8 @@ set(SRC
shader/nodes/node_shader_tex_sky.c
shader/nodes/node_shader_tex_voronoi.c
shader/nodes/node_shader_tex_wave.c
- shader/nodes/node_shader_tex_checker.c
- shader/nodes/node_shader_tex_brick.c
+ shader/nodes/node_shader_volume_isotropic.c
+ shader/nodes/node_shader_volume_transparent.c
shader/node_shader_tree.c
shader/node_shader_util.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 66ab15ce29f..e402924c04f 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -81,11 +81,15 @@ void register_node_type_sh_layer_weight(struct bNodeTreeType *ttype);
void register_node_type_sh_tex_coord(struct bNodeTreeType *ttype);
void register_node_type_sh_particle_info(struct bNodeTreeType *ttype);
void register_node_type_sh_script(struct bNodeTreeType *ttype);
+void register_node_type_sh_normal_map(struct bNodeTreeType *ttype);
+void register_node_type_sh_tangent(struct bNodeTreeType *ttype);
+void register_node_type_sh_ambient_occlusion(struct bNodeTreeType *ttype);
void register_node_type_sh_background(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_diffuse(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_glossy(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_glass(struct bNodeTreeType *ttype);
+void register_node_type_sh_bsdf_refraction(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_translucent(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_transparent(struct bNodeTreeType *ttype);
void register_node_type_sh_bsdf_velvet(struct bNodeTreeType *ttype);
diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
new file mode 100644
index 00000000000..7dfefc9ece0
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
@@ -0,0 +1,63 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_ambient_occlusion_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = {
+ { SOCK_SHADER, 0, N_("AO")},
+ { -1, 0, "" }
+};
+
+static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+}
+
+/* node type definition */
+void register_node_type_sh_ambient_occlusion(bNodeTreeType *ttype)
+{
+ static bNodeType ntype;
+
+ node_type_base(ttype, &ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out);
+ node_type_size(&ntype, 150, 60, 200);
+ node_type_init(&ntype, NULL);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_exec(&ntype, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion);
+
+ nodeRegisterType(ttype, &ntype);
+}
+
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
new file mode 100644
index 00000000000..99e66e39002
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c
@@ -0,0 +1,68 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_bsdf_refraction_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Roughness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("IOR"), 1.45f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f},
+ { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_bsdf_refraction_out[] = {
+ { SOCK_SHADER, 0, N_("BSDF")},
+ { -1, 0, "" }
+};
+
+static int node_shader_gpu_bsdf_refraction(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+{
+ if (!in[3].link)
+ in[3].link = GPU_builtin(GPU_VIEW_NORMAL);
+
+ return GPU_stack_link(mat, "node_bsdf_refraction", in, out);
+}
+
+/* node type definition */
+void register_node_type_sh_bsdf_refraction(bNodeTreeType *ttype)
+{
+ static bNodeType ntype;
+
+ node_type_base(ttype, &ntype, SH_NODE_BSDF_REFRACTION, "Refraction BSDF", NODE_CLASS_SHADER, NODE_OPTIONS);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_bsdf_refraction_in, sh_node_bsdf_refraction_out);
+ node_type_size(&ntype, 150, 60, 200);
+ node_type_init(&ntype, NULL);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_exec(&ntype, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_bsdf_refraction);
+
+ nodeRegisterType(ttype, &ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
new file mode 100644
index 00000000000..39fd8a5decc
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -0,0 +1,69 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_normal_map_in[] = {
+ { SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_normal_map_out[] = {
+ { SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_normal_map(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+{
+ NodeShaderNormalMap *attr = MEM_callocN(sizeof(NodeShaderNormalMap), "NodeShaderNormalMap");
+ node->storage = attr;
+}
+
+static int gpu_shader_normal_map(GPUMaterial *mat, bNode *UNUSED(node), GPUNodeStack *in, GPUNodeStack *out)
+{
+ return GPU_stack_link(mat, "node_normal_map", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+}
+
+/* node type definition */
+void register_node_type_sh_normal_map(bNodeTreeType *ttype)
+{
+ static bNodeType ntype;
+
+ node_type_base(ttype, &ntype, SH_NODE_NORMAL_MAP, "Normal Map", NODE_CLASS_OP_VECTOR, NODE_OPTIONS);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_normal_map_in, sh_node_normal_map_out);
+ node_type_size(&ntype, 250, 60, 250);
+ node_type_init(&ntype, node_shader_init_normal_map);
+ node_type_storage(&ntype, "NodeShaderNormalMap", node_free_standard_storage, node_copy_standard_storage);
+ node_type_exec(&ntype, NULL);
+ node_type_gpu(&ntype, gpu_shader_normal_map);
+
+ nodeRegisterType(ttype, &ntype);
+}
+
diff --git a/source/blender/nodes/shader/nodes/node_shader_tangent.c b/source/blender/nodes/shader/nodes/node_shader_tangent.c
new file mode 100644
index 00000000000..6c0d6d7cd9f
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_tangent.c
@@ -0,0 +1,60 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_tangent_out[] = {
+ { SOCK_VECTOR, 0, N_("Tangent"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node, bNodeTemplate *UNUSED(ntemp))
+{
+ NodeShaderTangent *attr = MEM_callocN(sizeof(NodeShaderTangent), "NodeShaderTangent");
+ attr->axis = SHD_TANGENT_AXIS_Z;
+ node->storage = attr;
+}
+
+/* node type definition */
+void register_node_type_sh_tangent(bNodeTreeType *ttype)
+{
+ static bNodeType ntype;
+
+ node_type_base(ttype, &ntype, SH_NODE_TANGENT, "Tangent", NODE_CLASS_INPUT, NODE_OPTIONS);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, NULL, sh_node_tangent_out);
+ node_type_size(&ntype, 150, 60, 200);
+ node_type_init(&ntype, node_shader_init_tangent);
+ node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage);
+ node_type_exec(&ntype, NULL);
+ node_type_gpu(&ntype, NULL);
+
+ nodeRegisterType(ttype, &ntype);
+}
+