Jump to content

  • Log In with Google      Sign In   
  • Create Account

Calculating tangents in a different way


Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
5 replies to this topic

#1 Relfos   Members   -  Reputation: 349

Like
0Likes
Like

Posted 09 September 2010 - 10:08 PM

For my voxel terrain editor, I need to calculate tangents for all generated vertices. By using the method of taking the UV coords, it produces bad results, because this terrain is using tri-planar texturing (3 sets of UV coords, interpolated using the normal).

If I understand correctly, the tangent and bitangent vectors are perpendicular to the normal, and follow the direction of the U and V.

My UVs are ourrently generated from the position of the vertices, something like
U = vertex.y * UVScale
V = vertex.y * UVScale
W = vertex.z * UVScale

I tried using the face normals to select the two coords of the the three (eg: when the face normal is pointing to the Y direction, pick X and Z for uvs).
This doesnt produce smooth tangent vectors.

Since the UVs are dependent from the position, we can assume they're always pointing in the positive direction, and somehow calculate a perpendicular vector to the normal, to get the tangent?

Sponsor:

#2 taby   Members   -  Reputation: 553

Like
0Likes
Like

Posted 10 September 2010 - 05:32 AM

Quote:
Original post by Relfos
...


If you only have one vector to start with, I think this might work... I think JYK showed me something like this once:

1) Find out which of the normal vector's components (N.x, N.y, or N.z) is the shortest/of the smallest value. For example, let's say that we've found the N.x component to be the shortest...

2) Make a second vector B, where the B.x component is of length 1, and the B.y and B.z components are of length 0. Again, I focus on N.x and B.x here only because I'm giving a specific example. It could have been N.y or N.z that was the shortest in the previous step.

3) Take the cross product of NxB = C to get a third vector.

4) The chances of C being of unit length by default is very very slim, so you must normalize C before continuing.

5) Take the cross product of CxN = B to get a final version of B.

You should now have a basis consisting of three orthogonal unit vectors N, B and C.

#3 PolyVox   Members   -  Reputation: 708

Like
0Likes
Like

Posted 10 September 2010 - 10:00 AM

If you can get access to a copy of ShaderX5 there is an article about building tangent frames in the pixel shader using the ddx and ddy instructions. I've never tried it but maybe it is useful to you: 2.6 Normal Mapping without Pre-Computed Tangents by Christian Schueler

#4 Eric Lengyel   Crossbones+   -  Reputation: 2925

Like
0Likes
Like

Posted 11 September 2010 - 01:15 AM

There are two tangent frames when using triplanar texturing. See Section 5.5.2 of the following:

http://www.terathon.com/lengyel/Lengyel-VoxelTerrain.pdf


#5 taby   Members   -  Reputation: 553

Like
0Likes
Like

Posted 11 September 2010 - 04:33 AM

Congratulations on your degree. That's totally awesome that your terrain editor is like a mini-3D paint/clay modeling program, with texture brushes and all. :)

I see the chapter 5.5.2 Tangent Space.

Please correct me if I'm wrong: basically you use the two tangent fields to avoid coordinate singularities? If so, is this is to do with making the surfaces orientable? I know these sound like silly questions, but I'm still learning a lot, and I ask honestly. :)

#6 mind in a box   Members   -  Reputation: 815

Like
0Likes
Like

Posted 13 September 2010 - 01:44 AM

Relfos, I think I have done just the same thing like you in my engine (With the PolyVox library).

I would find it very cool when I could see yours [smile]
Here's a news-posting explaining my terrain editors layer system (And a video!):
http://www.moddb.com/engines/wtech/news/wtech-voxel-based-terrain-layers-via-deferred-rendering

As you see, I am using triplanar texturing with normal mapping as well.

To get the tangents, I got some code from Nvidias GPU Gems 3 and modified it to fit my needs:


float3 GetTriPlanarNrmMap(Texture2D yzTexture,Texture2D zxTexture,Texture2D xyTexture,float2 TexScale, float NrmMapDepth, PixelShaderInput Input, float3 VertexPos, float3 Normals)
{
// Determine the blend weights for the 3 planar projections.
// N_orig is the vertex-interpolated normal vector.
float3 blend_weights = abs( Normals );

// Tighten up the blending zone:
blend_weights = (blend_weights +WEIGHT_BIAS) * WEIGHT_MUL;
blend_weights = max(blend_weights, 0);

// Force weights to sum to 1.0 (very important!)
blend_weights /= (blend_weights.x + blend_weights.y +
blend_weights.z ).xxx;

// Now determine a color value and bump vector for each of the 3
// projections, blend them, and store blended results in these two
// vectors:
float4 blended_color; // .w hold spec value
float3 blended_bump_vec;

// Compute the UV coords for each of the 3 planar projections.
// tex_scale (default ~ 1.0) determines how big the textures appear.
float2 coord1 = (VertexPos.yz * TexScale);
float2 coord2 = (VertexPos.zx * TexScale);
float2 coord3 = (VertexPos.xy * TexScale);

// This is where you would apply conditional displacement mapping.
//if (blend_weights.x > 0) coord1 = . . .
//if (blend_weights.y > 0) coord2 = . . .
//if (blend_weights.z > 0) coord3 = . . .

// Sample bump maps too, and generate bump vectors.
// (Note: this uses an oversimplified tangent basis.)
float2 bumpFetch1 = (TexUV(Tex2,coord1).xy -0.5)*NrmMapDepth;
float2 bumpFetch2 = (TexUV(Tex2,coord2).xy -0.5)*NrmMapDepth;
float2 bumpFetch3 = (TexUV(Tex2,coord3).xy -0.5)*NrmMapDepth;
float3 bump1 = float3(0, bumpFetch1.x, bumpFetch1.y);
float3 bump2 = float3(bumpFetch2.y, 0, bumpFetch2.x);
float3 bump3 = float3(bumpFetch3.x, bumpFetch3.y, 0);

blended_bump_vec = bump1.xyz * blend_weights.xxx +
bump2.xyz * blend_weights.yyy +
bump3.xyz * blend_weights.zzz;

return blended_bump_vec;
}



To use what this generates, you simply need to add the result of the function to your mesh's normal-vector.

I hope this could be useful for you.




Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.




PARTNERS