GLSL shader tangent and binormal calculation bug

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

GLSL shader tangent and binormal calculation bug

Post by TCM »

Hello

I have a spotlight shader which uses the normal, tangent and binormal. I get these from:

Code: Select all

   
vec3 Tangent = gl_MultiTexCoord1.xyz;
vec3 Binormal = gl_MultiTexCoord2.xyz;
In order to get normals, tangents and binormals i have to create a new mesh with tangents:

Code: Select all

irr::scene::IMesh* tangentMesh = smgr->getMeshManipulator()->
                                createMeshWithTangents(mesh->getMesh(0));
I am not sure WHY irrLicht does not load normals from models. If it is a memory saving issue, then i should have the option to load or not the normals.

Anyway, if i use tangents and binormals as gl_MultiTexCoordX then i get a lot of artifacts like here (picture2):

https://sites.google.com/site/damakukamely/home

However, if i chose to calculate the tangent and binormal inside the shader using:

Code: Select all

   vec3 rm_Tangent;
   vec3 Binormal;

   vec3 c1 = cross(gl_Normal, vec3(0.0, 0.0, 1.0)); 
   vec3 c2 = cross(gl_Normal, vec3(0.0, 1.0, 0.0)); 
   
   if(length(c1)>length(c2))
   {
      Tangent = c1;   
   }
   else
   {
      Tangent = c2;   
   }
   
   Tangent = normalize(Tangent);
   
   Binormal = cross(gl_Normal, Tangent); 
   Binormal = normalize(Binormal);
The i get a correct image (see picture1), here: https://sites.google.com/site/damakukamely/home.
But even this one does have some artifacts at some angles. I guess the problem is around if(length(c1)>length(c2)) or something like that.


The question is, it seems irrlicht has a bug and cannot properly calculate tangent and binormal. These should be very easy to calculate, they are just X products of the normals.

Second, how can i make irrLicht to load normals, and not recalculate them ?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Normals are always loaded and used by Irrlicht whre available. Binormals and tangents are not supported so far, but only .X supports them anyway. We could load them, but it's hard to choose whether to use a lightmap mesh (i.e. two texture coords) or binormals in advance of the loading. The .x file format does not tell you until you find the data somewhere inside.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

You are calculating the tangent space wrong.

The tangent and the binormal aren't calculated like that in graphics engines. Think of a triangle. It has 3 points, 3 normals and a set of texture coordinates, U and V. Then, the Tangent vector of a vertex is defined to be the vector which follows the positive U direction of the texture coordinates and the Binormal is defined to be the vector which follows the positive V direction.

The problem is that this can't be calculated inside a shader because you only see 1 point at any given time inside the shader code, and to calculate properly the U and V vectors you would need at least 2 points, so, it is imposible. It must be calculated inside the mesh. I've checked some times the tangent space calculations and it seems correct. Check the exporting format and the version of Irrlicht you are using. Export the normals, and in the material which uses the shader enable the normalize normals switch. Maybe it helps.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

You'll have to excuse my continous whining about it, but please drop the term binormal. It's not the right word. Normals(to surfaces)(in 3 dimensions with an orthonormal base) are perpendicular to surfaces. For every point on a surface, there are only two possible normals, which are paralell with each other, one on each side of the surface.
Wolfram mathworld wrote: In the field of computer graphics, two orthogonal vectors tangent to a surface are frequently referred to as tangent and binormal vectors. However, for a surface, the two vectors are more properly called tangent and bitangent vectors.
It's not my intent to belittle anyone, just to promote use of proper terms and make it easier for people to understand one another.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

Then you have a very long road ahead :) While what you mention is correct, in Open GL and DirectX the semantics are already BINORMAL0 and TANGENT0 or gl_Binormal and gl_Tangent and it is easier to refer to them as such than changing their names.

There are times where a name, although it is incorrect, is commonly accepted as the right thing, and is kept because it is what the majority understands.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

Ouch. I cant find any info on the gl_* variables though.. But even the dx variables/semantics seem to be found only in legacy interface.
Mel wrote:There are times where a name, although it is incorrect, is commonly accepted as the right thing, and is kept because it is what the majority understands.
This is true; But it is also true that it is not always the right thing to do. Insisting on doing the wrong thing and motivating it with the argument "It's always been that way" is not what i'd call smart.
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

Mel wrote:Think of a triangle. It has 3 points, 3 normals.
Why 3 normals?

3 points can determine a plane. A point cannot have a normal (to the surface) because a point has no dimension. The normal to the surface is a vector perpendicular to that surface. Am i missing something here???


Anyway, irrlicht does calculate tangents and binormals wrong. My way of calculating (not invented by me of course, i saw it in another shader) produced good results, though not perfect.
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

Mel wrote:I've checked some times the tangent space calculations and it seems correct. Check the exporting format and the version of Irrlicht you are using. Export the normals, and in the material which uses the shader enable the normalize normals switch. Maybe it helps.

Using the same mesh as Render Monkey. Render Monkey perfect, irrLicht artifacts.

I normalized the normals:
(setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
but no effect.
shadowslair
Posts: 758
Joined: Mon Mar 31, 2008 3:32 pm
Location: Bulgaria

Post by shadowslair »

TCM wrote:
Mel wrote:Think of a triangle. It has 3 points, 3 normals.
Why 3 normals?
3 points can determine a plane. A point cannot have a normal (to the surface) because a point has no dimension. The normal to the surface is a vector perpendicular to that surface. Am i missing something here???
Yes, you`re missing the point that a plane can have only one normal, but the triangles we`re using every day have per vertex normals - three vertices, 3 normals. If we don`t have 3 normals, we`ll never be able to use smoothing groups and the result will be like the one we constantly see exported through some majority of exporters to .3ds and the user is asking why his model looks so ugly. The default lighting is using per vertex lighting this way, otherwise we`d get per triangle lighting, which is even 3 times uglier. If we had only one normal per triangle, how`d we store that, and how`d we operate in the vertex shader? Of course we can always make all 3 of them pointing in the same direction if we need to.

I`m pretty sure Irrlicht calculates the normals, tangents and bitangents properly, although the result may not be exactly the one you wanted, because of the smoothing groups. You can get artifacts even if using different normalmaps - the tangent space Y direction can point up or down, and even (not that common) the tangent space X can point right or left (right is more common).

@Luben - You`re right pal, but many people have never heard the right term, and they may be kinda bewildered by the "new"( correct ) term. I still call it "binormal" because I`ve used so, even the hlsl semantic name is the same. All in all- why should it matter that much?! :D
"Although we walk on the ground and step in the mud... our dreams and endeavors reach the immense skies..."
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

Thanks, i knew i was missing something. I am using the very same 3ds file in RenderMonkey and in irrLicht, but i am getting different results.
Only normals are loaded from the file, tangent and binormal are calculated by irrLicht.
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

@shadowslair
It doesn't really matter. In fact, very little matters. It's just that people ought to do that which is right. Claiming something is something which it is not is not right, even if your used to it. But the most important reason to stop calling it 'binormal' might be because newcomers ought to learn it properly. Secondly, to make it easier to communicate. If you talk with me about binormals, then i think your talking about line(-segments), since that's the only reasonable thing to think.
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

@Luben

Most important is to define and explain them. I don't care how you call them, i need to know what they are and how to calculate them.
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

The BigWosh is the derp-product of the Nromal and the Tagrent. Any more questions?

Note that the result of a derp-product is in fact not a tecvor, but a peusod-tecvor, because the footednes of the orientation-definition can change. As such, the BigWosh is a peusod-tecvor, as is the Nromal and the Tagrent, since the derp-product of the Tagrent and the BigWosh (denoted by BigWosh € Tagrent) is the Nromal, and BigWosh € Normal = Tagrent. The results of a derp-product is garfunkeld to the operands, and when talking about definitions in 3 perplections made up of for example the Tagrent, Nromal and BigWosh, one usually calls the definition a garfunction. This can, in fact, be generalized to any number of perplections, as long as the criteria about all all definition-pieces being garfunkeled(with regard to each other) holds.

Another interesting product is the drep-product. The drep-product of two tecvors(In ecudilian definitions, that is if i remember correctly, garfunctions) is equal to 0 if they are lapparel, and |v1||v2|cos(a) where a is the smallest angle between the tecvors. The drep-product of the tecvors o and O is written as (o.O). An interesting property of the drep-product is that if you take the drep product of a single tecvor, you get the squared length of that tecvor.

If a garfunction consists of tecvors, of which the drep-product with themselves is exactly 1, one usually says that the garfunction is a gardenction. Working with gardenctions has many benefits over working with other definitions, such as it being horribly easy to calculate the lurk of rembrars, and unless you absolutely have to work with dazzling. The lurk of a rembrar which represents a gardenction is simply the terp of the rembrar!

(I'm sorry if i've forgotten to define and explain some term; if that is the case, tell me, and i shall endeavour to explain it all)
agamemnus
Posts: 283
Joined: Sun Jan 31, 2010 6:06 pm

Post by agamemnus »

I can only hope to be as brilliant a programmer as you, Luben. :D
TCM
Posts: 53
Joined: Mon May 24, 2010 9:29 pm

Post by TCM »

If all the industry is calling it binormal........

And this is not the point here. The point is calculating them, as it is clear that there is an issue with irrLicht.
Post Reply