Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated tangent has same direction as normal #1

Open
tksuoran opened this issue Apr 4, 2021 · 3 comments
Open

Generated tangent has same direction as normal #1

tksuoran opened this issue Apr 4, 2021 · 3 comments

Comments

@tksuoran
Copy link

tksuoran commented Apr 4, 2021

Is it a fair expectation that generated tangents should be different for normals?
Is there something I need to do to make it so?

I needed tangents for anisotropic light reflection and tried to use MikkTSpace for this.

I run into a problem where generated tangent has same direction as normal. This will cause lighting calculations to fail.

This happens with my cylinder primitive geometry. It generates X-axis aligned cylinder, so that 'bottom' end has normal (-1, 0, 0) and 'top' end has normal (1, 0, 0).

Here, for simplicity, I approximate the cylinder with minimum number of vertices. this makes both bottom and top just triangles.

I've added logging to my code so that I can get a trace of SMikkTSpaceInterface usage.

A minimal trace where I have isolated the geometry only to have one triangle, which is the top:

getNumFaces() num_faces = 1
getNumVerticesOfFace(iFace = 0) = 3
getNumFaces() num_faces = 1
getNumVerticesOfFace(iFace = 0) = 3
getNumFaces() num_faces = 1
getPosition(iFace = 0, iVert = 0) = 1, 0
getPosition(iFace = 0, iVert = 1) = 1, 0.8660254
getPosition(iFace = 0, iVert = 2) = 1, -0.8660254
getPosition(iFace = 0, iVert = 0) = 1, 0
getPosition(iFace = 0, iVert = 1) = 1, 0.8660254
getPosition(iFace = 0, iVert = 2) = 1, -0.8660254
getPosition(iFace = 0, iVert = 0) = 1, 0
getPosition(iFace = 0, iVert = 1) = 1, 0.8660254
getPosition(iFace = 0, iVert = 2) = 1, -0.8660254
getPosition(iFace = 0, iVert = 0) = 1, 0
getPosition(iFace = 0, iVert = 1) = 1, 0.8660254
getPosition(iFace = 0, iVert = 2) = 1, -0.8660254
getPosition(iFace = 0, iVert = 0) = 1, 0
getPosition(iFace = 0, iVert = 1) = 1, 0.8660254
getPosition(iFace = 0, iVert = 2) = 1, -0.8660254
getTexCoord(face = 0, vert = 0) = 0, 1
getTexCoord(face = 0, vert = 1) = 0.33333334, 1
getTexCoord(face = 0, vert = 2) = 0.6666667, 1
getNumVerticesOfFace(iFace = 0) = 3
setTSpace(fvTangent = 1, 0, 0, fvBiTangent = 0, 1, 0, fMagS = 1, fMagT = 1, bIsOrientationPreserving = 0, iFace = 0, iVert = 0) corner_id = 0
setTSpaceBasic(fvTangent = 1, 0, 0, fSign = -1, iFace = 0, iVert = 0) corner_id = 0
setTSpace(fvTangent = 1, 0, 0, fvBiTangent = 0, 1, 0, fMagS = 1, fMagT = 1, bIsOrientationPreserving = 0, iFace = 0, iVert = 1) corner_id = 1
setTSpaceBasic(fvTangent = 1, 0, 0, fSign = -1, iFace = 0, iVert = 1) corner_id = 1
setTSpace(fvTangent = 1, 0, 0, fvBiTangent = 0, 1, 0, fMagS = 1, fMagT = 1, bIsOrientationPreserving = 0, iFace = 0, iVert = 2) corner_id = 2
setTSpaceBasic(fvTangent = 1, 0, 0, fSign = -1, iFace = 0, iVert = 2) corner_id = 2

Interestingly, normals are not queried at all.

Attached log has trace for full cylinder geometry. It shows that normals are now queried, but face 7 still gets tangent == normal.

You can see the full geometry in the screenshot below. Face numbers are yellow, points are green. I do not currently have visualization for face corners, so the points probably do not have much value as is. Faces are filled with interpolated texture coordinates (scaled by 0.5).

cylinder_uv
cylinder_trace.txt

In case it helps:

Thanks!

@tksuoran
Copy link
Author

tksuoran commented Apr 4, 2021

I have realized that I need better texture coordinates. Most likely this should solve the issue.

@mmikk
Copy link
Owner

mmikk commented Apr 8, 2021

Sorry for the late response but I saw that you realized your issue. Indeed your UVs need to span an area.
Also are you using authored UVs or projected UVs? Projected UVs generally works very poorly at vertex level.

morten

@tksuoran
Copy link
Author

tksuoran commented Apr 8, 2021

Initially I used projected (spherical) UVs and indeed that did not work well.

I improved my cylinder primitive to generate proper texture coordinates for bases as well, but then I realized I can easily generate tangents directly as well. I still had other primitives, platonic solids for example, which did not have texture coordinates nor tangents. I ended up calculating per polygon projected texture coordinates like this:

texcoords

I know I probably could easily calculate tangents for these without going through texture coordinates. I still wanted to see how MikkTSpace handled these, as it is good to know if there is something that I can use as a generic solution. Then I noticed that only trinagles and quads are supported. So I virtually triangulated faces with centroid triangle fan. With that in place, I got this:

tangents

I don't have visualization for the virtual triangulation, but centroids are shown. There are now valid tangents everywhere, however, triangles in each face don't always agree on the tangent. Is this expected result?

I added post processing to pick a tangent that appears at least twice:

tangents2

Would it be possible to extent MikkTSpace to natively support faces with more than 4 corners?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants