Viewports and Frustums
Conceptually, a viewport is a two-dimensional (2D) rectangle onto which a 3D scene is projected. In the XNA Framework, the rectangle exists as as x- and y-coordinates within a 2D surface used by XNA as a rendering target. Properly positioning graphical objects on this surface requires a mathematical transform (known as a projection transform). This transform converts 3D vertices into the coordinate system of the viewport. Additionally, a viewport can specify the range of depth values for the render-target surface. This range usually lies between 0.0 and 1.0.
The Viewing Frustum
A viewing frustum is a 3D volume positioned relative to the viewport's camera. The shape of the volume affects how models are projected from camera space onto the screen. The most common type of projection, a perspective projection, is responsible for making objects near the camera appear bigger than objects in the distance. For perspective viewing, the viewing frustum can be visualized as a pyramid, with the camera positioned at the tip. This pyramid is intersected by a front and back clipping plane. The volume within the pyramid between the front and back clipping planes is referred to as the viewing frustum. Objects are visible only when they are in this volume.
Imagine that you are standing in a dark room and looking through a square window. This is a good representation of a viewing frustum. In this analogy, the near clipping plane is the window, and the back clipping plane is whatever finally interrupts your view - the skyscraper across the street, the mountains in the distance, or nothing at all. You can see everything inside the truncated pyramid that starts at the window and ends with whatever interrupts your view, and nothing else.
The viewing frustum is defined by a field of view (fov), and by the distances of the front and back clipping planes, which are specified in z-coordinates. You can create a perspective fov using the CreatePerspectiveFieldOfView method. For more information on setting up a frustum and perspective transformation, see How To: Make a Third-Person Camera.
You define a viewport rectangle in XNA by using the Viewport structure. For more information about using this structure in your game application, see Displays, Client Bounds, Viewports, and Back Buffers.
The Viewport structure contains four members - X, Y, Width, Height - that define the area of the render-target surface in which a scene is rendered. These values correspond to the destination rectangle, or viewport rectangle.
The specified values for the X, Y, Width, and Height members are screen coordinates relative to the upper-left corner of the render-target surface. The structure defines two additional members (MinDepth and MaxDepth), indicating the near and far view planes.
The depth buffer has a limited resolution which is distributed between the near and far clip planes. If these planes are too far apart, two objects could have the same depth value even though they lie on different depth planes. In cases like this, the depth buffer is unable to distinguish between them because of its limited resolution.
To avoid this situation, set your near clipping plane as high as possible without causing near-plane clipping issues. For instance, avoid settings such as 0.000001, which would certainly cause problems.
The XNA Framework assumes that the viewport clipping volume ranges from −1.0 to 1.0 in X, and from 1.0 to −1.0 in Y. These were the settings used most often by applications in the past. You can specify the viewport aspect ratio, used for the projection transform, with a call to CreatePerspectiveFieldOfView.
The XNA Framework uses the viewport location and dimensions to scale the vertices to fit a rendered scene into the appropriate location on the target surface. An internal matrix is applied to each vertex to scale vertices according to the viewport dimensions and desired depth range and translate them to the appropriate location on the render-target surface. This matrix also reverses the y-coordinate to reflect a screen origin at the top-left corner with y increasing downward. After this matrix is applied, vertices are still homogeneous. That is, they still exist as [x,y,z,w] vertices—and they must be converted to non-homogeneous coordinates before being sent to the rasterizer.
|The viewport scaling matrix incorporates the MinDepth and MaxDepth members of the Viewport structure to scale vertices to fit the specified depth range.|
Clearing a Viewport
Clearing the viewport resets the contents of the viewport rectangle on the render-target surface. It can also clear the depth and stencil buffer surfaces.
Use Clear to clear the various components of the viewport. Overloaded versions accept various parameters such as a set of rectangles, defining the areas on the surface to be cleared, or a ClearOptions enumeration that specifies which buffers or render target to clear.
Use the Clear method to clear stencil bits within a depth buffer. Set the options parameter to determine which render-target components are cleared. The color argument sets the color value of the render target after it has been cleared. The depth parameter clears the depth buffer to the specified depth: 0.0 is the closest distance, and 1.0 is the farthest. Finally, the stencil paramter resets the stencil bits to the specified value. Use integers ranging from 0 to 2n−1, where n is the stencil buffer bit depth.