- Home /
Shader for distorting a texture as if it were on a sphere
I'm trying to add 3D spheres with simple textures to my UI. Currently I'm doing this using cameras and render textures but this is not very performant. I'm thinking there must be a way to take a flat texture and a set of euler angles and produce a distortion which makes the texture appear as though it's on a rotated sphere.
Note that in the attached image, my examples are on an actual sphere. However in the UI it'd probably just be projected onto a square sprite which I then add a circular mask to.
I'm already somewhat capable with simple shaders but I'm not sure what to look into to start with this one. I'd appreciate if someone could point me in the right direction. Thanks.
Answer by Bunny83 · Dec 13, 2019 at 03:59 AM
Well, if you actually talk about just displaying a single quad in screen space with a special shader that actually shows a sphere with a texture mapped onto it, this is possible but not that trivial. You essentially do a manual ray-tracing in the fragment shader. You just need to specify all relevant information from outside. Also I barely use the gameobject based UI system so I'm not sure if you can actually use a custom material / shader for your element. However instead of normal UI element you could also use a normal Quad. I currently do not have the time to modify my raytrace shader I've written some time ago. I used it to render a to-scale earth sphere.
Since using an actual sphere mesh is always imprecise I created this raytrace shader. Together with the shader I used this script to draw a fullscreen overlay quad procedurally which essentially overlayed the raytraced earth sphere in the main camera view. It also updates the relevant shader variables like the position of the earth sphere and the rotation. Of course you wouldn't need most of that if you have a fix view and position of your virtual sphere. Note that I generate the usual UV-sphere texture coordinates in the shader. So the usual cylindrical mapping is used. Which means the top and bottom of the texture will be mapped to the north / south pole and have the greatest distortion in the mapping.
$$anonymous$$aybe if I find the time in the next days I can try to simplify the shader / script to suit your needs.
This is pretty fascinating. I have to say I thought ray tracing might be a bit overkill for what I'm looking for. I don't actually need the sphere to have shadowing or anything, I just need to sample a texture in such a way that it becomes distorted as though it were the surface of a sphere facing the camera. (Sort of an 'inverse mercator projection' or something.)
This is very cool, though! I'm curious is there a way to rotate the resulting sphere on its pivot? If yes, and this works in UI, then it may be exactly what I need.
EDIT: I was able to get it rotating by multiplying the local matrix passed in by a rotation matrix. Pretty straightforward.
EDIT 2: So if I add this to a UI image, -something- does show up, a tiny sliver of the sphere which appears and disappears see$$anonymous$$gly at random. Worked very nicely in scene view on a quad, though.
Answer by TomazTreven · Dec 12, 2019 at 11:38 AM
For moving texture around in shader you can manipulate uv's in shader, for morphing quad into sphere you can change position of vertices in vertex shader.. but such huge modification is probably not going to work well.. maybe it can be checked what exactly is causing performance issues in current solution
I don't want to move any vertices or just move a texture around, I want to make a flat 2D texture appear like it's a rotating sphere, while still just being a flat image on a texture.
"maybe it can be checked what exactly is causing performance issues in current solution "
Doing that is what led me here. :)
Answer by WheresMommy · Dec 12, 2019 at 01:01 PM
Why not take the offset of yozr texture and scale and rotate always pointing to center?
That wouldn't produce any distortion. I want it to appear as though it's a rotating sphere.
It will distort with the scale. So moving up and down would distort on y axis, left right on x
Scaling the y axis will squish the iris uniformly, like an oval, but if you look at the second example, the correct distortion would squash the bottom half more and appear to bring the pupil and iris closer together along the bottom.
In addition, I'm only using an eye as an example. I would like this to work for any texture.