Tangents computation problem back

Board: Home Board index Raytracing General Development

(L) [2011/12/20] [ost by spectral] [Tangents computation problem] Wayback!

Hi,

I have a model that I try to render, the problem is that some shaders (diffuse, phong, etc...) use a method based on the 'tangent' to re-orient a vector based on the face orientation.

By example, in the diffuse shader I do the following :
Code: [LINK # Select all]Lwo = CosineSampleHemisphere2(u1, u2);
return LocalToWorld(N, T, Lwo);

The problem is that my tangents are non-uniform. To show this I have create a 'tangent shader' that show the tangent distribution. Here is the result :

[IMG #1 Image]

In fact the problem is that I have no UV mapping, so I can't compute any tangent !!
Do you have a solution for this kind of problem ? How to compute a tangent without UV mapping !

BTW : when rendering with blender or Maxwell there is no such problem !
[IMG #1]:Not scraped: https://web.archive.org/web/20200804083322im_/https://lh6.googleusercontent.com/-GdTe2x_CjWo/TvB-gQhw6VI/AAAAAAAAALQ/S8piuSl9-SM/s523/ErrorTangents.png
(L) [2011/12/20] [ost by ingenious] [Tangents computation problem] Wayback!

I assume you have some routine that, given a normal vector, generates a local frame around it. Maybe it has consistency problems. How does it look like?
(L) [2011/12/20] [ost by spectral] [Tangents computation problem] Wayback!

Yes, of course ...

To generate the tangents, I use the code from here : [LINK http://www.terathon.com/code/tangent.html]
I have also try other solutions, but none gives the correct solution !

I think that my problem is to compute the UVs when I only have the normals, because the tangents are computed from the UVs, if the Uvs are incorrect then the tangents too !
I'm searching for a good algorithm to do this... I have one but it seems not robust in some cases (Yes, for the other scenes I have no problem).

Thanks
(L) [2011/12/21] [ost by spectral] [Tangents computation problem] Wayback!

I have finally found the problem, it was due to an pre-processing task, a kind of mesh-reorganization where I have miss to reorganize my UVs too !!!!

Thanks for your help...
(L) [2011/12/30] [ost by spectral] [Tangents computation problem] Wayback!

Finally not,

I'm still playing to find a correct way to compute good tangents... but no way... for each technique a model fail to be rendered correctly !

To test I use 3 models and a "tangent shader" (I can provide the obj or the blender model if someone is interested):
- Lego man
- RS8 model
- Cornell box with 2 spheres

I have use several techniques for now :
- Precomputed techniques : where I compute all the tangents once (preprocessing)
- Live computation

I have try to mix all theses methods, but no way... I can render all my models without problems !

If someone has more information about the right way of doing this... ??

Pre-computation
- Code from the assimp library : [LINK http://assimp.svn.sourceforge.net/viewvc/assimp/trunk/code/CalcTangentsProcess.cpp?revision=1027&view=markup]
- Code from [LINK http://www.terathon.com/code/tangent.html]
- Code from NVidia NVMeshMender.cc : [LINK http://www.koders.com/cpp/fid2F46C590DE141A7E8BECB3F4AE8038E1CBEFFED3.aspx]

Live computation methods : based on the N vector
Code: [LINK # Select all]void GetOrthonormalBasis(clVector3 N, clDualVector3* TnBiT)
{
    N = normalize(N);
    clVector3 up = (clVector3)(0.f, 1.f, 0.f);
   
    if (fabs(dot(up, N)) > 0.8f)
      up = (clVector3)(1.f, 0.f, 0.f);
   
    TnBiT->v1 = normalize(cross(up, N));
    TnBiT->v2 = normalize(cross(N, TnBiT->v1));
}
Code: [LINK # Select all]void GetOrthonormalBasis(const clVector3 v0, clDualVector3* dv)
{
    if (fabs(v0.x) > fabs(v0.y))
    {
        float invLen = 1.f / sqrt(v0.x * v0.x + v0.z * v0.z);
        dv->v1.x = -v0.z * invLen;
        dv->v1.y = 0.f;
        dv->v1.z = v0.x * invLen;
    }
    else
    {
        float invLen = 1.f / sqrt(v0.y * v0.y + v0.z * v0.z);
        dv->v1.x = 0.f;
        dv->v1.y = v0.z * invLen;
        dv->v1.z = -v0.y * invLen;
    }
    dv->v2 = cross(v0, dv->v1);
}
Code: [LINK # Select all]void GetOrthonormalBasis(clVector3 N, clDualVector3* TnBiT)
{
    // Reference:
    //
    //   Hughes, J. F., and Moller, T. Building an Orthonormal Basis from a Unit Vector.
    //   Journal of Graphics Tools 4, 4 (1999), 33-35.
    //   http://www.cs.brown.edu/research/pubs/pdfs/1999/Hughes-1999-BAO.pdf
    // Compute u so that it is orthogonal to n.
    if (fabs(N.x) < fabs(N.y))
    {
        if (fabs(N.x) < fabs(N.z))
        {
            // N.x is the smallest component.
            TnBiT->v1.x =  0.f;
            TnBiT->v1.y = -N.z;
            TnBiT->v1.z =  N.y;
        }
        else
        {
            // N.z is the smallest component.
            TnBiT->v1.x = -N.y;
            TnBiT->v1.y =  N.x;
            TnBiT->v1.z =  0.f;
        }
    }
    else
    {
        if (fabs(N.y) < fabs(N.z))
        {
            // N.y is the smallest component.
            TnBiT->v1.x = -N.z;
            TnBiT->v1.y =  0.f;
            TnBiT->v1.z =  N.x;
        }
        else
        {
            // N.z is the smallest component.
            TnBiT->v1.x = -N.y;
            TnBiT->v1.y =  N.x;
            TnBiT->v1.z =  0.f;
        }
    }
    // u is orthogonal to n, but not unit-length. Normalize it.
    TnBiT->v1 = normalize(TnBiT->v1);
    // Compute v.
    TnBiT->v2 = cross(TnBiT->v1, N);
}
Live computation methods : based on the uv coordinates
Code: [LINK # Select all]    if (!isnan(vp0.Tex.u))
    {
        // Compute deltas for triangle partial derivatives of normal
        float du1 = vp1.Tex.u - vp0.Tex.u;
        float du2 = vp2.Tex.u - vp0.Tex.u;
        float dv1 = vp1.Tex.v - vp0.Tex.v;
        float dv2 = vp2.Tex.v - vp0.Tex.v;
        
        float determinant = du1 * dv2 - dv1 * du2;
        if (determinant != 0.f)
        {
            float invdet = 1.f / determinant;
        
            clVector3 dp1 = vp1.P - vp0.P;
            clVector3 dp2 = vp2.P - vp0.P;
            
            clVector3 dpdu = (dv2 * dp1 - dv1 * dp2) * invdet;
            rayHit->T = normalize(cross(rayHit->Ng, dpdu));
            return;
        }
    }
(L) [2012/01/04] [ost by graphicsMan] [Tangents computation problem] Wayback!

I can't see anything wrong at first glance.  What specifically is going wrong?  If you always create a local basis using just the normal in a live fashion, even that doesn't work?  That's what I'd use first to make sure everything else is okay.
(L) [2012/01/05] [ost by spectral] [Tangents computation problem] Wayback!

Thanks,

In fact, you can see the tangent distribution on the image (the car). In the reality, the tangents are corrects, but suddenly  switch of direction and so, by example when I use a diffuse shader (or any other tangent based shader) the same effect appear  !
(L) [2012/01/05] [ost by jbarcz1] [Tangents computation problem] Wayback!

>> spectral wrote:Thanks,

In fact, you can see the tangent distribution on the image (the car). In the reality, the tangents are corrects, but suddenly  switch of direction and so, by example when I use a diffuse shader (or any other tangent based shader) the same effect appear  !
Can you post an image of a diffuse shader with "live calculation"?    With discontinuous tangents like that I could imagine seeing some hard lines in the noise (though they should get reduced as the image converges), but if you just use the normals and compute a local frame on the fly, I'd expect it work much better
(L) [2012/01/05] [ost by graphicsMan] [Tangents computation problem] Wayback!

I think that it should only be true that you might see lines if you use quasi monte carlo.  If you use a good RNG, it shouldn't matter if your basis flips across an edge... each basis should have a completely uncorrelated effect on it's shading position.  This won't work at all, of course, if you have an anisotropic material, but let's worry about that after this first problem gets fixed.
(L) [2012/01/06] [ost by spectral] [Tangents computation problem] Wayback!

You're right, it is what I think to but sampling is also based on MLT rules... so it is not always uniform, but anyway it should not be a problem for diffuse surface. I will investigate for the RNG number too !
But anyway for anisotropic I will have the problem too !

Thx

back