From 9d260eedeb83776416981e2f3a8af9bb5605e1d2 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 17 Oct 2012 23:09:12 +0000 Subject: Fix #32904: strange pattern on subdivided cube with anistropic shader. Now tangents from generated coordinates are computed per pixel on the fly, avoids bad interpolation of singularities. --- intern/cycles/blender/blender_mesh.cpp | 73 +-------------------------------- intern/cycles/kernel/svm/bsdf_ward.h | 4 +- intern/cycles/kernel/svm/svm_geometry.h | 29 ++++++++++++- intern/cycles/render/nodes.cpp | 8 +++- 4 files changed, 37 insertions(+), 77 deletions(-) diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index bbc9b00b0dc..7055cf981c7 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -33,22 +33,6 @@ CCL_NAMESPACE_BEGIN /* Find/Add */ -static float3 tangent_uv_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); -} - static float3 tangent_from_triangle(float3 v0, float3 v1, float3 v2, float3 tx0, float3 tx1, float3 tx2) { float3 duv1 = tx2 - tx0; @@ -176,9 +160,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< } /* create texcoord-based tangent attributes */ - bool need_tangent = mesh->need_attribute(scene, ATTR_STD_TANGENT); - - if(need_tangent) { + if(mesh->need_attribute(scene, ATTR_STD_TANGENT)) { BL::Mesh::tessface_uv_textures_iterator l; for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) { @@ -233,15 +215,13 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< /* normalize tangent vectors */ for(int i = 0; i < mesh->verts.size(); i++) tangents[i] = normalize(tangents[i]); - - need_tangent = false; } } /* create generated coordinates. todo: we should actually get the orco * coordinates from modifiers, for now we use texspace loc/size which * is available in the api. */ - if(mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_tangent) { + if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) { Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); float3 loc = get_float3(b_mesh.texspace_location()); float3 size = get_float3(b_mesh.texspace_size()); @@ -257,55 +237,6 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector< for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) generated[i++] = get_float3(v->co())*size - loc; - - /* if there is no UV map, we generated tangents from generated coordinates */ - if(need_tangent) { - Attribute *attr = mesh->attributes.add(ATTR_STD_TANGENT, ustring("Tangent")); - - /* compute average tangents per vertex */ - float3 *tangents = attr->data_float3(); - memset(tangents, 0, sizeof(float3)*mesh->verts.size()); - - size_t fi = 0; /* face index */ - for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++fi, ++f) { - int4 vi = get_int4(f->vertices_raw()); - - float3 tx0 = tangent_uv_from_generated(generated[vi[0]]); - float3 tx1 = tangent_uv_from_generated(generated[vi[1]]); - float3 tx2 = tangent_uv_from_generated(generated[vi[2]]); - - float3 v0 = mesh->verts[vi[0]]; - float3 v1 = mesh->verts[vi[1]]; - float3 v2 = mesh->verts[vi[2]]; - - /* calculate tangent for the triangle; - * get vertex positions, and find change in position with respect - * to the texture coords in the first texture coord dimension */ - float3 tangent0 = tangent_from_triangle(v0, v1, v2, tx0, tx1, tx2); - - if(nverts[fi] == 4) { - /* quad tangent */ - float3 tx3 = tangent_uv_from_generated(generated[vi[3]]); - float3 v3 = mesh->verts[vi[3]]; - float3 tangent1 = tangent_from_triangle(v0, v2, v3, tx0, tx2, tx3); - - tangents[vi[0]] += 0.5f*(tangent0 + tangent1); - tangents[vi[1]] += tangent0; - tangents[vi[2]] += 0.5f*(tangent0 + tangent1); - tangents[vi[3]] += tangent1; - } - else { - /* triangle tangent */ - tangents[vi[0]] += tangent0; - tangents[vi[1]] += tangent0; - tangents[vi[2]] += tangent0; - } - } - - /* normalize tangent vectors */ - for(int i = 0; i < mesh->verts.size(); i++) - tangents[i] = normalize(tangents[i]); - } } } diff --git a/intern/cycles/kernel/svm/bsdf_ward.h b/intern/cycles/kernel/svm/bsdf_ward.h index 1407078b7bb..d167566bb75 100644 --- a/intern/cycles/kernel/svm/bsdf_ward.h +++ b/intern/cycles/kernel/svm/bsdf_ward.h @@ -39,8 +39,8 @@ CCL_NAMESPACE_BEGIN __device void bsdf_ward_setup(ShaderData *sd, ShaderClosure *sc, float ax, float ay) { - float m_ax = clamp(ax, 1e-5f, 1.0f); - float m_ay = clamp(ay, 1e-5f, 1.0f); + float m_ax = clamp(ax, 1e-4f, 1.0f); + float m_ay = clamp(ay, 1e-4f, 1.0f); sc->data0 = m_ax; sc->data1 = m_ay; diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 30afd6322a7..e0f9e337652 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -20,6 +20,22 @@ 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; @@ -36,8 +52,17 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); object_normal_transform(kg, sd, &data); } - else - data = normalize(sd->dPdu); + 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); + } } else data = normalize(sd->dPdu); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 6030c9f49c1..73c45665431 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1246,8 +1246,10 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes) { ShaderInput *tangent_in = input("Tangent"); - if(!tangent_in->link) + if(!tangent_in->link) { attributes->add(ATTR_STD_TANGENT); + attributes->add(ATTR_STD_GENERATED); + } ShaderNode::attributes(attributes); } @@ -1595,8 +1597,10 @@ GeometryNode::GeometryNode() void GeometryNode::attributes(AttributeRequestSet *attributes) { - if(!output("Tangent")->links.empty()) + if(!output("Tangent")->links.empty()) { attributes->add(ATTR_STD_TANGENT); + attributes->add(ATTR_STD_GENERATED); + } ShaderNode::attributes(attributes); } -- cgit v1.2.3