1
\$\begingroup\$

I have a sphere and in Fragment shader, I have available lat / lon position (in radians) for every fragment. I have a texture of a single dot. I need to map this single dot (or any other texture) repeatedly over the sphere and create a pattern like a "golf ball" (for example this sample: https://www.shadertoy.com/view/Xs2fWy - however the dots are calculated directly from raytracing plus the code is not commented, so not very clear). I donw want to pregenerate texture, because I want to dynamicly change the number of dots.

Is there a solution how to achieve this only in fragment shader? I cannot modify anything else.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Animation varying the _Density parameter

Here's a starting point, using a float variable _Density to control how many repeats you get.

        float3 n = normalize(IN.worldNormal);
        // Get longitude (x) in the range -1...1, and latitude (y) in the range (-0.5...0.5).
        float2 longLat = float2(atan2(n.z, n.x), asin(n.y)) / 3.141592653589f;

        // Count how many rows we can fit top to bottom at our selected density.
        float rowCount = ceil(_Density);
        // If it's odd, the 0th row sits at the equator. Otherwise, we need to shift it half a row.
        float even = fmod(rowCount + 1.0f, 2.0f);

        // Scale and rount our latitude to find which row this fragment is in.
        float y = longLat.y * rowCount;
        float row = round(y - 0.5f * even);

        // Compute the radius around the sphere along the center of this row.
        float rowRadians = (row + 0.5f * even) * 3.141592653589f / rowCount;
        float rowRadius = cos(rowRadians);
        // Round this to get the number of texture repeats horizontally.
        float rowRepeats = round(rowRadius * _Density * 2.0f);

        // Make our texture coordinates.
        float2 uv;
        uv.x = longLat.x * rowRepeats/2.0f;
        uv.y = y - row + (1.0f - even) * 0.5f;

        // TODO: Calculate mipmap/gradients to avoid artifacts at seams.
        fixed4 c = tex2D(_MainTex, uv).a * _Color;

Because we jump around UV space when we transition between rows, or where a row wraps-around on itself, we get some shimmery mipmapping artifacts at these transitions. An improved version would calculate which mip level to sample with tex2Dlod, or better yet, compute gradient vectors to use for anisotropic filtering with tex2Dgrad, to avoid the artifacts in the auto-calculated versions.

Another potential improvement would be to stamp one copy of the texture at each of the north and south poles, so that the tightest ring isn't quite so pinched in the middle.

Sample of the effect

\$\endgroup\$
1
  • \$\begingroup\$ Works perfectly, thank you very much. \$\endgroup\$ Commented Jul 17, 2020 at 13:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .