Looks nice.
Some feedback:
You can replace
vec2 resolution = vec2(CoronaVertexUserData.x,CoronaVertexUserData.y);
with
vec2 resolution = CoronaVertexUserData.xy;
or simply use the right-hand side directly in later steps.
This
vec2 position = gl\_FragCoord.xy / resolution.xy; position.y \*= resolution.y/resolution.x;
seems a little odd, unless it’s actually exploiting the subtle numerical precision difference between floating point numbers and mathematical ones. If not, the division and multiplication by the y-component cancel, so you could just write
vec2 position = gl\_FragCoord.xy / resolution.xx;
or
vec2 position = gl\_FragCoord.xy / resolution.x;
instead.
Lastly, if you’ll need to support older devices, the line
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) \* 43758.5453);
might be better served with something like
#if GL\_FRAGMENT\_PRECISION\_HIGH == 1 return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) \* 43758.5453); #else return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) \* 437.585453); #endif
though you’d have to experiment to be sure. (For the constant and the details I’m about to mention, see page 3 of the reference card.) Basically, any floating-point number is interpolated between adjacent powers of 2. If you have 1 / 65536 precision, you can get pretty close to that number (between 32768 and 65536, you can land on multiples of 0.5), but if your device can only muster 1024ths, you won’t (in that same range, you’d snap to multiples of 32!), which will probably be too choppy for small objects like your stars.