# How to make illusion of round world?

I want to make a flat world, but i want to split it into pieces which will load in segments (for better optimization), and when you are at the end of map it will start loading segments from the beginning again. And I want to make an illusion of roundness (only optical effect if possible). For example, when you watch ships on the horizon, you see their masts first.

I'm asking only for theoretical ideas, so you don't need to send any scripts.

• Something like youtube.com/watch?v=_kY4v-L3rvY ? Uses shaders to present a flat environment as curved. – fadden Feb 25 '16 at 18:26
• There was an old game that I use to play called Populous 3 that had round worlds. They would tile a rectangular map around the world so that the tops and sides of the rectangle would connect (even though it is impossible to wrap a rectangle around a sphere in this way). It was a very clever illusion and they pulled it off very well. – JSideris Feb 28 '16 at 20:06
• Thanks, but for me is vertex shader better option. – T. Růžička Feb 28 '16 at 21:56

You can do this purely in a vertex shader. You'd want to apply this shader to everything you render.

One trick though that you can do is weight it so that the nearby objects are flat out to say 100 meters. I'd recommend this because in an FPS game the distortion on objects requires you to change things. (Players will aim at things wrong). If you keep the nearby regions flat then start the curve at a distance it'll look the same without having interaction problems.

Here's an image to understand. (I don't have the code at the moment on this machine, but it's only a few lines if I remember correctly).

Since you asked for code. I can't vet this code 100%, but I did see images of it working. (I wrote pseudocode for a friend who converted it to HLSL and the images showed it working).

cbuffer matrix_buffer
{
matrix world;
matrix view;
matrix projection;
};

struct vertex_input_type
{
float4 position : POSITION;
float3 normal : NORMAL;
};

struct pixel_input_type
{
float4 position : SV_POSITION;
float3 normal : NORMAL;
};

{
pixel_input_type output;

input.position.w = 1.0f;

#if 0
output.position = mul(world, input.position);
output.position = mul(view, output.position);
output.position = mul(projection, output.position);
#else
float4 viewPosition = float4(0, 20.0, 0, 1);
float seaLevel = 0.0;
float4 vertex = input.position;
matrix model = world;

vertex = mul(model, vertex);
float2 diff = vertex.xz - viewPosition.xz;
float angleX = -length(diff) / radius;
float angleY = atan2(diff.x, diff.y);
float3x3 rotateX =
{
1, 0, 0,
0, cos(angleX), -sin(angleX),
0, sin(angleX), cos(angleX)
};
float3x3 rotateY =
{
cos(angleY), 0, sin(angleY),
0, 1, 0,
-sin(angleY), 0, cos(angleY)
};
vertex = float4(mul(rotateY, mul(rotateX, float3(0, radius + vertex.y - seaLevel, 0))) + float3(0, -radius, 0), 1);
vertex = mul(projection, mul(view, vertex));
output.position = vertex;
#endif

output.normal = input.normal;

return output;
}

• Thanks a lot. Is it called somehow? So i can look for code on my own. – T. Růžička Feb 25 '16 at 19:21
• It'll be a few hours until I get home. In the mean-time here's another image: i.imgur.com/RKzQifZ.png This one shows the regions that require loading based on the maximum height a camera can get to. Also en.wikipedia.org/wiki/Tangent_lines_to_circles – Sirisian Feb 25 '16 at 19:47
• @T.Růžička I updated with the only code sample I have in my old notes. I hope it helps. – Sirisian Feb 26 '16 at 8:50
• Thaks, it helped – T. Růžička Feb 26 '16 at 8:54
• Do you know how to use it in Unity please? – T. Růžička Mar 1 '16 at 13:59