I’m doing a texture mapping to a sphere. For finding UV coordinates I’m applying these formulas.
for u = 0.5 + arctan2(dz,dx)/2*pi
for v = 0.5 - arcsin(dy)/pi
I get wrong texturing.
How should I change those u and v parameters to make the texture fit on my sphere?
What you are doing is mappint cartesian to spherical coordinates. From the tip of my head, the mapping from spherical to cartesian should be something like this:
x = r * cos( deta ) * cos( phi )
z = r * sin( data ) * cos( phi )
y = r * sin( phi )
y / r = sin( phi )
phi = arcsin(y / r)
we can tweak phi a little to fall in our desired texture coordinate range and I guess that’s what
you are doing when computing v. Notice how my version divides ‘y’ by the radius and yours doesn’t.
Your version is entirely independend of the radius.
Regarding the other angle:
z / x = r*sin(deta)cos(phi) / rcos(deta)*cos(phi)
z / x = sin(deta) / cos(deta)
z / x = tan(deta)
deta = arctan( z / x )
deta = arctan2( z, x )
Again, we can tweak the value a bit to fall into our texture coordinate range, which is what you
are doing to compute ‘u’. Notice that here we don’t need the radius as we divide two input
coordinates that both have the radius as a factor, thus we can cross out the radius.
Once you’ve solved that issue, you may encounter another. If you try to map a rectangle to a sphere using the “obvious” 2D texture coordinates (i.e. a rectangular grid in texture space), you’ll get a visible kink along the diagonal of each quad (assuming that the quads are large enough for the kink to be visible).
The problem is that such a mapping isn’t affine (a quad can only have an affine texture mapping if it is a parallelogram). When the implementation splits the quads into triangles, the mapping for each triangle will be affine, but it will be different for the two triangles making up a quad.
Unfortunately, the only easy solution is to make the quads small enough that the disparity isn’t visible.
You can use a projection which preserves horizontal scaling, e.g. asinusoidal projection, but it needs to adjusted for the fact that the “sphere” is actually a piecewise-linear approximation, so the texture has to be designed for a specific mesh resolution.
Or you can use a fragment shader which corrects the interpolated texture coordinates back to lat/lon based upon the actual mesh resolution.