Cycles: 4 new nodes.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 6 Nov 2012 19:59:02 +0000 (19:59 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 6 Nov 2012 19:59:02 +0000 (19:59 +0000)
* 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

40 files changed:
intern/cycles/blender/blender_mesh.cpp
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/closure/bsdf_ward.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/background.cpp
intern/cycles/kernel/osl/osl_closures.cpp
intern/cycles/kernel/osl/osl_closures.h
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/kernel/shaders/CMakeLists.txt
intern/cycles/kernel/shaders/node_ambient_occlusion.osl [new file with mode: 0644]
intern/cycles/kernel/shaders/node_geometry.osl
intern/cycles/kernel/shaders/node_normal_map.osl [new file with mode: 0644]
intern/cycles/kernel/shaders/node_refraction_bsdf.osl [new file with mode: 0644]
intern/cycles/kernel/shaders/node_tangent.osl [new file with mode: 0644]
intern/cycles/kernel/shaders/node_ward_bsdf.osl
intern/cycles/kernel/shaders/stdosl.h
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_closure.h
intern/cycles/kernel/svm/svm_geometry.h
intern/cycles/kernel/svm/svm_tex_coord.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/attribute.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
intern/cycles/util/util_attribute.cpp
intern/cycles/util/util_types.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/editors/space_node/drawnode.c
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_nodetree_types.h
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_shader.h
source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c [new file with mode: 0644]
source/blender/nodes/shader/nodes/node_shader_bsdf_refraction.c [new file with mode: 0644]
source/blender/nodes/shader/nodes/node_shader_normal_map.c [new file with mode: 0644]
source/blender/nodes/shader/nodes/node_shader_tangent.c [new file with mode: 0644]

index 0e13479a761e7759a87e72e713a500a551941a74..69b330db4833160e72ff5673da09cabf376dcd15 100644 (file)
@@ -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);
+                       }
                }
        }
 
index 1f8d86a7f7038c5d50bceb5f73c5a7f661f826d0..6dc0bbdb90e08b8b091714f386c0610a96ec1e63 100644 (file)
@@ -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;
                }
        }
index 9c81548a2c33735adf721801fa42f0f7706296da..dbddcf20dba1b4eaf302b4d7a9a6fdee43366032 100644 (file)
@@ -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;
index 817f254a5e50e25b2903a933e0ac73df664ea981..585068ce8e23a5c7d5391643a31059b45b309b52 100644 (file)
@@ -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);
                                        }
                                }
index 86886a6a2319c3aea58309898c6c70c26008052f..1af5e048ad99cc4d4ee88ff368a5416f13e67e1c 100644 (file)
@@ -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)
index 98d998351a761cbe6df6b6bde810fe36dc4c1f06..d4d88466688df0a59e4b64b5c0cd5610f48c0e12 100644 (file)
@@ -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 {
index b6e9473b7bfc8bfabab01dd323b17eb77f0d6afc..eed4446cddc1c625764fd42e0ae34c3328766442 100644 (file)
@@ -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
 
index 73e96643df7ccced9fba58703101f74bdd210fd8..de572d0e585dfe445f4093bad6d5da2b287d58b5 100644 (file)
@@ -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
index 574cb685db52fafb37be80c730955ea099d0e478..9137bad58d3d3ea2c024065f0470a0fc736f530c 100644 (file)
@@ -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) \
index 8b71ac30ab6a6272a824e67c00ed24a8a7296ab6..5d26f543efc4b4ba76e85f09b3c27f666bd6fc5f 100644 (file)
@@ -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;
index 00ab52a1d133c2205bb5148210769a041daef813..4f5a97c1bb637ec2d229be19b7d9b75d390de798 100644 (file)
@@ -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 (file)
index 0000000..57a06f3
--- /dev/null
@@ -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();
+}
+
index 953c5d1fa2b640c5030ef3c0b6e489c483d086d5..3940b98eec13633197002a8b84945880141d0016 100644 (file)
@@ -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 (file)
index 0000000..e238313
--- /dev/null
@@ -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 (file)
index 0000000..0cf9d46
--- /dev/null
@@ -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 (file)
index 0000000..731af89
--- /dev/null
@@ -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)));
+}
+
index 03a0477038e7d112b4b7ec85130e2c66a1b042a8..e5c6f0ad7051a277f79b7e5bba72e4fca98c24b0 100644 (file)
@@ -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);
index 4237291c7a46fa00e91ffcd60c4d207a3f39b0a8..c55def2b47a0011a6a7c57549f9e6a3b31ee337f 100644 (file)
@@ -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;
index 698ef5016f02630e5228bc81d7eeeaff54ec2243..886fce63fd41a2fd722bc4c2bf1881aba6a77a70 100644 (file)
@@ -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:
index 11ce3b7c5d186b74fd769e91bef10c8b730666fe..f378d24463d85c93be3c770d742b3db513fbbb41 100644 (file)
@@ -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;
 
@@ -158,6 +158,31 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st
 #ifdef __CAUSTICS_TRICKS__
                        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);
@@ -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)
index 8e772f849c7662b7c4c5fee179b9400a1973f550..68177493f4ebddc4b5aa692168f9f0132746f28e 100644 (file)
@@ -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;
index 6bd8f2ac69cbc164ff97aebf223386941a02320d..2f73f7b9d40efaa23d88200df1a34d5bfd2bdb2c 100644 (file)
@@ -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
 
index 77df373a159360b83387bd237e224a86adf9f453..54767f3c87f11c5aa3bbe350eba723b2f47dbc58 100644 (file)
@@ -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
 
index c7a9ab3e51a70406b9fdd4ec11ddc0f784b13625..95941c14b6c40da286a324e87f63c868f1ef1e89 100644 (file)
@@ -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)
index d7bf71337f6f707aa4b06345a73cf55a94768576..4f50de11edf1a83c46f180239543243a7a71b8d2 100644 (file)
@@ -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
 
index d90cae5f66861ae2dba709cff6cad845748d6942..27b07769e28a0d9500d44cc6cd4bcb4f0d71d9e0 100644 (file)
@@ -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__ */
index 163a92902f3d555cd7945dfe1f48cf9d04293eb4..057fb6213e99dba06c2619bdb3831ca7f98baf9e 100644 (file)
@@ -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)
index f2c02cadcbfa369e4e0689481f19b0583efdb265..fe530d727adbbc5ed1f660e8efcac0475cbbd7d1 100644 (file)
@@ -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,
index 29e03f66bcc6f3e36bea5ad97291affba16f8f88..b365d93b246c1632189df0a3b20e597dafb7dd07 100644 (file)
@@ -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
index 153eb5271c53a35d0aff7004c3f06077ad164c25..2d76484b60a75e834e601f3c93cf140790e580fb 100644 (file)
@@ -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);
index 0938562857ba4ffad7b183e2979ff22b9a09eb22..b99842502ec2ca97c1294a45134790051669f4f3 100644 (file)
@@ -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:
index c73ba87754f9e0335037492fff73e2f0212dd559..3437e6dfcf19f84ac4f7064512ba21b1daeb1afe 100644 (file)
@@ -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
index 312469340a7c5e24fbb0ccc950dbf39ee812a4db..93f37682aa3f014f2b2f57236d5c1fcc22e08111 100644 (file)
@@ -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;
index c45c9b714425069e5761428ee8a31dd8e1cccc51..fbbcbae6c12c33afe11b50111e874f4d64d4e875 100644 (file)
@@ -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",""      )
index 323a534c989a5df544851736c4be3f3c2fc2d40c..7dca4d07b240a76249c36ef5c90a5d310963f69a 100644 (file)
@@ -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
 
index 66ab15ce29f3a10a24c2661a0990fe1018cc2d63..e402924c04f38da9c8a96d5d5965cc1350deaed8 100644 (file)
@@ -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 (file)
index 0000000..7dfefc9
--- /dev/null
@@ -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 (file)
index 0000000..99e66e3
--- /dev/null
@@ -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 (file)
index 0000000..39fd8a5
--- /dev/null
@@ -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 (file)
index 0000000..6c0d6d7
--- /dev/null
@@ -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);
+}
+