Hi. That "GetUV_PhiDelta" is actually another function of mine that you need. I have a registration step early on where you add shader building blocks and then the loader (which you'll see used in the examples) does its best to stitch these together. This is the intermediate form.

This certainly isn't perfect (I don't trust my hand-crafted parser much, for one thing; I'm aware of a couple more dedicated alternatives but haven't mustered the will to try to swap them out) but does give some power.

I'm actually hoping in the near future to start on a connect-the-nodes sort of shader editor, once I clean up some of the necessary bits from another project for reuse.

I ran the shader test code and printed the kernel it gave me:

#define FRAGMENT_SHADER
#define SPHERE_NO_DISCARD
P_UV float PI = 4. * atan(1.);
P_UV float TWO_PI = 8. * atan(1.);
P_UV float PI_OVER_TWO = 2. * atan(1.);
P_UV float ONE_OVER_PI = 1. / atan(1.);
P_UV float ONE_OVER_TWO_PI = .5 / atan(1.);
P_POSITION vec2 GetUV_PhiDelta (P_POSITION vec2 diff, P_POSITION float dphi)
{
P_POSITION float dist_sq = dot(diff, diff);
#ifndef SPHERE_NO_DISCARD
if (dist_sq > 1.) return vec2(-1.);
#endif
P_POSITION float z = sqrt(1. - dist_sq);
P_POSITION float phi = atan(z, diff.x);
P_POSITION float angle = .5 + phi / TWO_PI;
#ifdef SPHERE_PINGPONG_ANGLE
angle = mod(angle + dphi, 2.);
angle = mix(angle, 2. - angle, step(1., angle));
#else
angle = fract(angle + dphi);
#endif
return vec2(angle, .5 + asin(diff.y) / PI);
}
P_COLOR vec4 FragmentKernel (P_UV vec2 uv)
{
uv = GetUV_PhiDelta(2. * uv - 1., -CoronaTotalTime / 7.);
if (uv.s < 0.) return vec4(0.);
return CoronaColorScale(texture2D(CoronaSampler0, uv));
}

Some of that is unused, since this is all code-generated and doesn't have any cleanup-type logic.

The "phi" comes from spherical coordinates. The shader has a box whose coordinates go from 0 to 1, so the rest of the phi math follows from that.

For the left-to-right rotation case, you basically want to replace the **CoronaTotalTime**-based delta with your own input. Vertically, you would need to make this account for theta. In the samples for this plugin I have a control that might be a starting point for what you want. (Stuff along these lines was why I even bothered submitting it for a 2D framework! )

You'll notice the obvious texture wrapping (common in samples like this). There are some difficulties in really getting nice-looking borders, basically since a flat rect can't be distorted into a sphere.