PS2 Linux Programming
Cube With Frustum Clipping
This tutorial will illustrate frustum clipping with VU1 and provide background to the techniques being used.
The application of the projection transform to a vertex produces a 4 dimensional vector with components (x, y, z, w). As presented in the tutorial “Viewing in 3 Dimensions”, if the vertex is within the view frustum it satisfies the following conditions:
x < w < -x
y < w < -y
z < w < -x
If any of these conditions is false, the vertex will be outside the view frustum and the vertex should be clipped. The vector unit has an instruction and set of flags specifically to cater for frustum clipping and these are shown below:
The application of this single clip instruction to any vertex, as illustrated below, will therefore set the appropriate clipping flags in the clipping flag register.
clipw.xyz Vert, Vert
In addition to this, the clipping flag register maintains a record of clipping judgements from the previous three vertices, so it is possible to make decisions on which vertex and/or polygon to draw based upon the values that are currently held within the clipping flag register.
Setting The Size of the Clipping Frustum
It is important that the size of the clipping frustum is carefully chosen otherwise undesirable visual artefacts will be produces. Consider the situation shown below, where one of the vertices of a triangle is just outside the viewable screen area.
If the clipping frustum tightly covers the viewable screen area, the triangle shown above will be clipped even although most of the triangle should be visible. The “trick” is to make the clipping frustum cover a much larger area than the visible screen area.
Consider therefore the diagram shown below.
The inner rectangle is the screen area and the outer square is the total drawing area of the PS2 which has dimensions 4096 x 4096 pixels. It is the larger frustum which covers the large square that is used for clipping whilst the inner rectangle is used for the actual drawing. It can be seen that only triangles with vertices outside the enlarged frustum will be clipped. This ensures that most triangles which are partly in the drawing area and partly out will be drawn since they are unlikely to be outside the larger drawing area. This prevents unpleasant visual artefacts.
The PS2 has a scissoring feature which by default is set to the viewable screen area. Therefore, only pixels that appear within the visible screen area will be rendered by the graphics synthesiser.
Configuring the Clipping Frustum
Recall from the tutorial “Transforming a Coloured Quad With VU1” that the projection matrix used scaling factors which scaled the x coordinate of a vertex by SW/4096 and the y coordinate by SH/4096. This has the effect of reducing x and y by the associated factor. Considering the x coordinate, if it is reduced by the factor SW/4096 then instead of clipping commencing at SW it will now commence at SW * 4096/SW or 4096. Likewise, clipping of the y coordinate will also occur at 4096.
Thus, the effect of applying the scaling factor to the projection matrix is to create a clip frustum which is much larger than the frustum surrounding the drawing area. This ensures that most triangles within the drawing area are in fact drawn, and the scissoring within the graphics synthesiser ensures that only on-screen pixels are rendered.
Note that the scaling factors applied to the projection matrix does not affect the z coordinate with the z coordinate still being clipped at the near and far clipping planes.
Only changes to the VCL have been made to accommodate clipping. The main.cpp program is exactly the same as in the previous tutorial. The following extract illustrates the clipping process:
MatrixMultiplyVertex Vert, fTransform, Vert
clipw.xyz Vert, Vert ; This instruction checks if the vertex is outside
; the viewing frustum. If it is, then the appropriate
; clipping flags are set
fcand vi01, 0x3FFFF ; Bitwise AND the clipping flags with 0x3FFFF, ; this makes sure that we get the clipping judgement for
; the last three verts (i.e. that make up the triangle
; we are about to draw)
; A true result of fcand will put 1 into vi01.
; A false result of fcand will put 0 into vi01
iaddiu iADC, vi01, 0x7FFF ; Add 0x7FFF. If any of the clipping flags were set this
; will cause the triangle not to be drawn
; (a value of 0x8000 that is stored in the w
; component of XYZ2 will set the ADC bit, which tells
; the GS not to perform a drawing kick on this
isw.w iADC, StartVert(iVertPtr) ; Finally store the ADC bit back to memory
After the vertex is transformed, it can be seen that frustum clipping is accomplished with four instructions. The first instruction performs the clipping tests and sets the appropriate clipping flags. The clipping flag register is checked for any clipping flags being set using the fcand instruction. The immediate value of 0x3FFFF supplied checks the clipping flags for the current and the last two vertices. If any of these clipping flags are set, then the current triangle should not be drawn. If any of the clipping flags are set, the value of 1 in loaded into the integer register vi01, otherwise 0 will be loaded into vi01. vi01 is then added to the immediate value of 0x7FFF which will store 0x8000 in the iADC register if clipping is to take place and 0x7FFF otherwise. The value of 0x8000 will set the ADC flag of the vertex and prevent a drawing kick. The value of 0x7FFF will not set the ADC bit allowing the drawing kick to take place. Finally, the ADC value is stored back to memory in the appropriate location within the vertex data.
On running the program, a rotating cube is displayed on screen. The cube can be rotated round the viewer using the left and right direction buttons. When the cube is rotated out of the frustum it is clipped and no undesirable visual artefacts are produced.
This tutorial has demonstrated frustum clipping using vector unit 1. Background information to the clipping process has also been described.
Dr Henry S Fortuna
University of Abertay Dundee