diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-05 02:31:32 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-11-05 02:31:32 +0400 |
commit | 2ba840652de83e0f546baaf0e10836bd6571731f (patch) | |
tree | 904321ea5fdfed97c02718236eb7645552e82bc0 /intern | |
parent | 110a36a8ab4cf688e6f2b6ec7398f8473a4896b9 (diff) |
Cycles: improve Anisotropic BSDF node, changing the Roughness U/V inputs to
Roughness, Anisotropy and Rotation. Also a fix for automatic tangents and
OSL attribute handling.
Meaning of new sockets explained in the documentation:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Nodes/Shaders#Anisotropic
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_object.h | 3 | ||||
-rw-r--r-- | intern/cycles/kernel/osl/osl_services.cpp | 28 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/node_geometry.osl | 24 | ||||
-rw-r--r-- | intern/cycles/kernel/shaders/node_ward_bsdf.osl | 27 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_closure.h | 20 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_geometry.h | 47 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 3 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 26 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 2 | ||||
-rw-r--r-- | intern/cycles/util/util_attribute.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/util/util_math.h | 23 |
12 files changed, 143 insertions, 64 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index b1b1a638219..a0feec90203 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -141,7 +141,7 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la /* create attribute */ /* todo: create float4 attribute for sign */ - Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent")); + Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("tangent")); float3 *tangent = attr->data_float3(); for (int i = 0; i < nverts.size(); i++) { diff --git a/intern/cycles/kernel/kernel_object.h b/intern/cycles/kernel/kernel_object.h index 2fa9443766e..112bfbb86b5 100644 --- a/intern/cycles/kernel/kernel_object.h +++ b/intern/cycles/kernel/kernel_object.h @@ -84,7 +84,8 @@ __device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg, } else { Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); - *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); + if(itfm) + *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); return tfm; } diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index ade085c795d..ac26fc1c18d 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -393,25 +393,25 @@ static bool set_attribute_float3_3(float3 P[3], TypeDesc type, bool derivatives, static bool get_mesh_attribute(KernelGlobals *kg, const ShaderData *sd, const OSLGlobals::Attribute& attr, const TypeDesc& type, bool derivatives, void *val) { - if (attr.type == TypeDesc::TypeFloat) { - float fval[3]; - fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, - (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); - set_attribute_float(fval, type, derivatives, val); - return true; - } - else if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || + if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { - /* todo: this won't work when float3 has w component */ float3 fval[3]; fval[0] = triangle_attribute_float3(kg, sd, attr.elem, attr.offset, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); set_attribute_float3(fval, type, derivatives, val); return true; } - else + else if (attr.type == TypeDesc::TypeFloat) { + float fval[3]; + fval[0] = triangle_attribute_float(kg, sd, attr.elem, attr.offset, + (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + set_attribute_float(fval, type, derivatives, val); + return true; + } + else { return false; + } } static void get_object_attribute(const OSLGlobals::Attribute& attr, bool derivatives, void *val) @@ -598,7 +598,7 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri if (it != attribute_map.end()) { const OSLGlobals::Attribute& attr = it->second; - + if (attr.elem != ATTR_ELEMENT_VALUE) { /* triangle and vertex attributes */ if (tri != ~0) @@ -613,11 +613,11 @@ bool OSLRenderServices::get_attribute(void *renderstate, bool derivatives, ustri else { /* not found in attribute, check standard object info */ bool is_std_object_attribute = get_object_standard_attribute(kg, sd, name, type, derivatives, val); + if (is_std_object_attribute) return true; - else { - return get_background_attribute(kg, sd, name, type, derivatives, val); - } + + return get_background_attribute(kg, sd, name, type, derivatives, val); } return false; diff --git a/intern/cycles/kernel/shaders/node_geometry.osl b/intern/cycles/kernel/shaders/node_geometry.osl index a3831cbec9c..953c5d1fa2b 100644 --- a/intern/cycles/kernel/shaders/node_geometry.osl +++ b/intern/cycles/kernel/shaders/node_geometry.osl @@ -32,7 +32,6 @@ shader node_geometry( { Position = P; Normal = NormalIn; - Tangent = normalize(dPdu); TrueNormal = Ng; Incoming = I; Parametric = point(u, v, 0.0); @@ -46,5 +45,28 @@ shader node_geometry( Position += Dy(Position); Parametric += Dy(Parametric); } + + /* first try to get tangent attribute */ + vector T; + + if (getattribute("geom:tangent", T)) { + /* ensure orthogonal and normalized (interpolation breaks it) */ + 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); + } + } } diff --git a/intern/cycles/kernel/shaders/node_ward_bsdf.osl b/intern/cycles/kernel/shaders/node_ward_bsdf.osl index e204be123b8..03a0477038e 100644 --- a/intern/cycles/kernel/shaders/node_ward_bsdf.osl +++ b/intern/cycles/kernel/shaders/node_ward_bsdf.osl @@ -20,11 +20,32 @@ shader node_ward_bsdf( color Color = color(0.8, 0.8, 0.8), - float RoughnessU = 0.0, - float RoughnessV = 0.0, + float Roughness = 0.0, + float Anisotropy = 0.0, + float Rotation = 0.0, normal Normal = N, + normal Tangent = normalize(dPdu), output closure color BSDF = diffuse(Normal)) { - BSDF = Color * ward(Normal, normalize(dPdu), RoughnessU, RoughnessV); + /* rotate tangent around normal */ + vector T = Tangent; + + if(Rotation != 0.0) + T = rotate(T, Rotation*2.0*M_PI, point(0.0, 0.0, 0.0), Normal); + + /* compute roughness */ + float RoughnessU, RoughnessV; + float aniso = clamp(Anisotropy, -0.99, 0.99); + + if(aniso < 0.0) { + RoughnessU = Roughness*(1.0 + aniso); + RoughnessV = Roughness/(1.0 + aniso); + } + else { + RoughnessU = Roughness/(1.0 - aniso); + RoughnessV = Roughness*(1.0 - aniso); + } + + BSDF = Color * ward(Normal, T, RoughnessU, RoughnessV); } diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index b72fad26a1f..11ce3b7c5d1 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -211,8 +211,24 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st sc->T = stack_load_float3(stack, data_node.z); svm_node_closure_set_mix_weight(sc, mix_weight); - sc->data0 = param1; - sc->data1 = param2; + /* rotate tangent */ + float rotation = stack_load_float(stack, data_node.w); + + if(rotation != 0.0f) + sc->T = rotate_around_axis(sc->T, sc->N, rotation * 2.0f * M_PI_F); + + /* compute roughness */ + float roughness = param1; + float anisotropy = clamp(param2, -0.99f, 0.99f); + + if(anisotropy < 0.0f) { + 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); + } sd->flag |= bsdf_ward_setup(sc); break; diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 501fed95002..8e772f849c7 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -20,22 +20,6 @@ CCL_NAMESPACE_BEGIN /* Geometry Node */ -__device_inline float3 svm_tangent_from_generated(float3 P) -{ - float length = len(P); - - if(length == 0.0f) - return make_float3(0.0f, 0.0f, 0.0f); - - float u = 0.0f; - if(!(P.x == 0.0f && P.y == 0.0f)) - u = (1.0f - atan2f(P.x, P.y))/(2.0f*M_PI_F); - - float v = 1.0f - acosf(clamp(P.z/length, -1.0f, 1.0f))/M_PI_F; - - return make_float3(u, v, 0.0f); -} - __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset) { float3 data; @@ -45,27 +29,30 @@ __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: { - if(sd->object != ~0) { - int attr_offset = find_attribute(kg, sd, ATTR_STD_TANGENT); + /* first try to get tangent attribute */ + int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_TANGENT): 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); + 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_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 { - attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED); - - if(attr_offset != ATTR_STD_NOT_FOUND) { - data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); - svm_tangent_from_generated(data); - object_normal_transform(kg, sd, &data); - } - else - data = normalize(sd->dPdu); + /* otherwise use surface derivatives */ + data = normalize(sd->dPdu); } } - else - data = normalize(sd->dPdu); break; } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 13c06a922cc..14f23992664 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -355,6 +355,9 @@ void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<Att /* set object attributes */ foreach(AttributeRequest& req, attributes.requests) { + if(req.element == ATTR_ELEMENT_NONE) + continue; + OSLGlobals::Attribute osl_attr; osl_attr.elem = req.element; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 42ab3fe17aa..d7bf71337f6 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1214,7 +1214,7 @@ BsdfNode::BsdfNode() add_output("BSDF", SHADER_SOCKET_CLOSURE); } -void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2) +void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3) { ShaderInput *color_in = input("Color"); ShaderInput *normal_in = input("Normal"); @@ -1231,6 +1231,14 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * compiler.stack_assign(param1); if(param2) compiler.stack_assign(param2); + if(param3) + compiler.stack_assign(param3); + + if(normal_in->link) + compiler.stack_assign(normal_in); + + if(tangent_in && tangent_in->link) + compiler.stack_assign(tangent_in); compiler.add_node(NODE_CLOSURE_BSDF, compiler.encode_uchar4(closure, @@ -1240,14 +1248,9 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * __float_as_int((param1)? param1->value.x: 0.0f), __float_as_int((param2)? param2->value.x: 0.0f)); - if(normal_in->link) - compiler.stack_assign(normal_in); - if(tangent_in) { - if(tangent_in->link) - compiler.stack_assign(tangent_in); - - compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, tangent_in->stack_offset); + compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, tangent_in->stack_offset, + (param3)? param3->stack_offset: SVM_STACK_INVALID); } else { compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset); @@ -1272,8 +1275,9 @@ WardBsdfNode::WardBsdfNode() add_input("Tangent", SHADER_SOCKET_VECTOR, ShaderInput::TANGENT); - add_input("Roughness U", SHADER_SOCKET_FLOAT, 0.2f); - add_input("Roughness V", SHADER_SOCKET_FLOAT, 0.2f); + add_input("Roughness", SHADER_SOCKET_FLOAT, 0.2f); + add_input("Anisotropy", SHADER_SOCKET_FLOAT, 0.5f); + add_input("Rotation", SHADER_SOCKET_FLOAT, 0.0f); } void WardBsdfNode::attributes(AttributeRequestSet *attributes) @@ -1290,7 +1294,7 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes) void WardBsdfNode::compile(SVMCompiler& compiler) { - BsdfNode::compile(compiler, input("Roughness U"), input("Roughness V")); + BsdfNode::compile(compiler, input("Roughness"), input("Anisotropy"), input("Rotation")); } void WardBsdfNode::compile(OSLCompiler& compiler) diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 0508bf6b266..d90cae5f668 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -193,7 +193,7 @@ class BsdfNode : public ShaderNode { public: SHADER_NODE_CLASS(BsdfNode) - void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2); + void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL); ClosureType closure; }; diff --git a/intern/cycles/util/util_attribute.cpp b/intern/cycles/util/util_attribute.cpp index 3a1c2b6f332..163a92902f3 100644 --- a/intern/cycles/util/util_attribute.cpp +++ b/intern/cycles/util/util_attribute.cpp @@ -30,6 +30,8 @@ const char *attribute_standard_name(AttributeStandard std) return "uv"; else if(std == ATTR_STD_GENERATED) return "generated"; + else if(std == ATTR_STD_TANGENT) + return "tangent"; else if(std == ATTR_STD_POSITION_UNDEFORMED) return "undeformed"; else if(std == ATTR_STD_POSITION_UNDISPLACED) diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 0b6f020ade5..70adee4385b 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1069,6 +1069,29 @@ __device_inline float3 safe_divide_color(float3 a, float3 b) return make_float3(x, y, z); } +/* Rotation of point around axis and angle */ + +__device_inline float3 rotate_around_axis(float3 p, float3 axis, float angle) +{ + float costheta = cosf(angle); + float sintheta = sinf(angle); + float3 r; + + r.x = ((costheta + (1 - costheta) * axis.x * axis.x) * p.x) + + (((1 - costheta) * axis.x * axis.y - axis.z * sintheta) * p.y) + + (((1 - costheta) * axis.x * axis.z + axis.y * sintheta) * p.z); + + r.y = (((1 - costheta) * axis.x * axis.y + axis.z * sintheta) * p.x) + + ((costheta + (1 - costheta) * axis.y * axis.y) * p.y) + + (((1 - costheta) * axis.y * axis.z - axis.x * sintheta) * p.z); + + r.z = (((1 - costheta) * axis.x * axis.z - axis.y * sintheta) * p.x) + + (((1 - costheta) * axis.y * axis.z + axis.x * sintheta) * p.y) + + ((costheta + (1 - costheta) * axis.z * axis.z) * p.z); + + return r; +} + CCL_NAMESPACE_END #endif /* __UTIL_MATH_H__ */ |