Fisheye Raycasting

2    05 Jan 2017 15:19 by u/psioniq

I'm trying to fake the curvature of a planet using a fisheye post-processing effect, but in doing so, I'll need to transform the rays being cast from screen space (like mouse position), to compensate for the effect.

This is how the fisheye post-effect is calculated for the shader (the source and destination are render textures with the same dimensions as the viewport):

float oneOverBaseSize = 80.0f / 512.0f; // to keep values more like in the old version of fisheye
float ar = (source.width * 1.0f) / (source.height * 1.0f);
fisheyeMaterial.SetVector ("intensity", new Vector4 (strengthX * ar * oneOverBaseSize, strengthY * oneOverBaseSize, strengthX * ar * oneOverBaseSize, strengthY * oneOverBaseSize));
Graphics.Blit (source, destination, fisheyeMaterial);

So, how would I go about compensating for that calculation when casting a ray from screen space?

Vector2 mousePos = Input.mousePosition;
// modify mouse position here?
Ray ray = Camera.main.ScreenPointToRay(mousePos);
Physics.SphereCast(ray, pointerSize, out hit, 2000f, mask); // hit contains a point where the ray hit a physical object in the scene
// or modify hit point here?

3 comments

1

What are strengthX and strengthY?

0

They are, in lack of a better term; 'stretching values' - they determine the vertical and horizontal strength of the fisheye effect.

I had a look at the shader and made this solution:

  public static Vector2 FisheyeCoord(Vector2 screenPosition)
    {
        float w = Screen.width;
        float h = Screen.height;
        float oneOverBaseSize = 80.0f / 512.0f; // to keep values more like in the old version of fisheye
        float ar = w / h;
        Vector4 matrix = new Vector4(strengthX * ar * oneOverBaseSize, strengthY * oneOverBaseSize, strengthX * ar * oneOverBaseSize, strengthY * oneOverBaseSize);
        Vector2 mPos = new Vector2(screenPosition.x / w, screenPosition.y / h);
        Vector2 coords = mPos;
        coords = (coords - new Vector2(0.5f, 0.5f)) * 2.0f;
        Vector2 realCoordOffs;
        realCoordOffs.x = (1f - coords.y * coords.y) * matrix.y * (coords.x);
        realCoordOffs.y = (1f - coords.x * coords.x) * matrix.x * (coords.y);
        Vector2 fPos = mPos - realCoordOffs;
        fPos.x *= w;
        fPos.y *= h;
        return fPos;
    }

Could probably be cleaned up a bit (don't really need a Vector4, as the x/z and y/w values are identical), but it works - thanks for showing interest though :)