Tangents computation problem

Practical and theoretical implementation discussion.
spectral
Posts: 382
Joined: Wed Nov 30, 2011 2:27 pm
Contact:

Tangents computation problem

Post by spectral » Tue Dec 20, 2011 12:24 pm

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: 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 :

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 !
Spectral
OMPF 2 global moderator

ingenious
Posts: 282
Joined: Mon Nov 28, 2011 11:11 pm
Location: London, UK
Contact:

Re: Tangents computation problem

Post by ingenious » Tue Dec 20, 2011 4:39 pm

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?
Image Click here. You'll thank me later.

spectral
Posts: 382
Joined: Wed Nov 30, 2011 2:27 pm
Contact:

Re: Tangents computation problem

Post by spectral » Tue Dec 20, 2011 10:23 pm

Yes, of course ...

To generate the tangents, I use the code from here : 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
Spectral
OMPF 2 global moderator

spectral
Posts: 382
Joined: Wed Nov 30, 2011 2:27 pm
Contact:

Re: Tangents computation problem

Post by spectral » Wed Dec 21, 2011 8:28 am

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...
Spectral
OMPF 2 global moderator

spectral
Posts: 382
Joined: Wed Nov 30, 2011 2:27 pm
Contact:

Re: Tangents computation problem

Post by spectral » Fri Dec 30, 2011 12:37 pm

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 : http://assimp.svn.sourceforge.net/viewv ... iew=markup
- Code from http://www.terathon.com/code/tangent.html
- Code from NVidia NVMeshMender.cc : http://www.koders.com/cpp/fid2F46C590DE ... FFED3.aspx

Live computation methods : based on the N vector

Code: 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: 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: 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: 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;
		}
	}
Spectral
OMPF 2 global moderator

graphicsMan
Posts: 164
Joined: Mon Nov 28, 2011 7:28 pm

Re: Tangents computation problem

Post by graphicsMan » Wed Jan 04, 2012 6:23 pm

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.

spectral
Posts: 382
Joined: Wed Nov 30, 2011 2:27 pm
Contact:

Re: Tangents computation problem

Post by spectral » Thu Jan 05, 2012 8:22 am

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 !
Spectral
OMPF 2 global moderator

jbarcz1
Posts: 6
Joined: Sun Dec 11, 2011 11:47 pm

Re: Tangents computation problem

Post by jbarcz1 » Thu Jan 05, 2012 3:43 pm

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

graphicsMan
Posts: 164
Joined: Mon Nov 28, 2011 7:28 pm

Re: Tangents computation problem

Post by graphicsMan » Thu Jan 05, 2012 5:25 pm

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.

spectral
Posts: 382
Joined: Wed Nov 30, 2011 2:27 pm
Contact:

Re: Tangents computation problem

Post by spectral » Fri Jan 06, 2012 11:16 am

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
Spectral
OMPF 2 global moderator

Post Reply