Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering infinitely large plane

I want to render a plane so that it looks as if it goes to infinity in all directions. I want the plane boundary in the distance to be the horizon.

Using a simple mesh does not work - the computer can't render infinitely many triangles. Even if this was possible, the camera frustum would cut out the distant polygons and create a gap between the plane boundary and the horizon.

A workaround is to compute the horizon mathematically: finding points on the plane, which also lie on the plane at infinity. Connecting these points and two corners of the viewport creates a trapezoid which represents the sought plane. However, this way the plane can not be lit properly, or applied a texture, or anything else which requires a fine triangulation...

like image 430
Violin Yanev Avatar asked Oct 18 '12 23:10

Violin Yanev


2 Answers

You can draw an infinite plane using the standard rasterization pipeline. The homogeneous coordinates it uses can represent "ideal" points (otherwise known as vanishing points or points at infinity) just as happily as regular Euclidean points, and likewise it is perfectly practical to set up a projection matrix which places the far plane at infinity.

A simple way to do this would be to use one triangle per quadrant, as follows:

vertices [x,y,z,w], for drawing an (x,y) coordinate plane, at (z==0):
  0: [ 0, 0, 0, 1 ]
  1: [ 1, 0, 0, 0 ]
  2: [ 0, 1, 0, 0 ]
  3: [-1, 0, 0, 0 ]
  4: [ 0,-1, 0, 0 ]

draw 4 triangles using indices:
  (0,1,2); (0,2,3); (0,3,4); (0,4,1)

If you want a test pattern (like an infinite checkerboard), you will have to deal with the fact that stretching your triangles to infinity will distort any standard texture. However, you can write a pixel shader that determines the color based on the actual 3D point (i.e., use x and y from the worldspace (x,y,z) coordinates), ignoring the (distorted) texture coords altogether.

You could choose between two constant colors based on parity (for a checkerboard), or tile a texture by sampling it based on the fractional part of your chosen coordinates.


Note that OpenGL's clip space is [-1..1] for each of x, y, and z. You can compute the appropriate projection matrix by evaluating the limits as far clip distance f increases without bound:

clip coords: [x]  =  [ n/r             ]  * view coords [x]
             [y]     [     n/t         ]                [y]
             [z]     [          -1 -2n ]                [z]
             [w]     [          -1   0 ]                [w]

Where (as in the link): n is the near clip plane, r is half the frustum width at the near clip plane, and t is half the frustum height at the near clip plane.

I have not tested the above matrix, so it's worth what you paid for it. Also be aware that the depth value will lose its precision as you approach infinity...

Although, the precision at closer distances will be likely be fine -- e.g., at any given distance, the depth resolution in the (near:infinity) case should be about 10% less than the case where the (near:far) ratio is (1:10).

like image 192
comingstorm Avatar answered Oct 15 '22 03:10

comingstorm


Your viewing frustum, which is a capped pyramid built from 4 clip planes on the sides and on the top/bottom, and on a near and a far plane is "infinite" (it is not infinite, but since you cannot see anything outside the frustum, it is as infinite as it can be).

Drawing the bottom side of your capped pyramid (a quad, or two triangles) therefore is a plane that is "infinite", going to the horizon. Or, for that matter, any quad with its corner points on the near and far planes.

like image 3
Damon Avatar answered Oct 15 '22 04:10

Damon