PS2 Linux Programming

 

 

Back Face Culling

 

Introduction

 

This tutorial illustrates a method of using VU1 to cull a triangle from the render pipeline if it is facing away from the camera. The winding order of the vertices of the triangle (clockwise or counter clockwise) is used to determine whether the front or back face of the triangle is facing the camera. If the back is facing the camera the triangle is not rendered.

 

To illustrate the technique in operation, there is a rotating triangle rendered in the scene. If the triangle is facing the camera it is rendered with each vertex having a different colour. If the triangle is facing away from the camera it is rendered in a solid white colour.

 

 

Background

 

 

 

Figure 1

 

 

Figure 1 illustrates a triangle with three vertices V1, V2 and V3. The vector cross product (D) is taken between the vectors (V2-V1) and (V2-V1) and the vector C, from the vertex V1 to the camera position VC, is obtained. The vector dot product between C and D determines the orientation of the triangle relative to the camera. The orientation of the triangle is determined from the sign of the dot product.

 

Included within the VU1 macro file supplied by Sony (vcl_sml.i) there is a macro called TriangleWinding.

 

TriangleWinding   result, vert1, vert2, vert3, eyepos

 

This macro has five parameters; vert1, vert2 and vert3 are the three triangle vertices and eyepos is the position of the camera. result is the output of the macro which is non-zero if the winding is clockwise. In essence, the macro executes the algorithm described above and “result” is used to determine the facing of the triangle relative to the camera.

 

 

VU1 Micro Code

 

In order to undertake back face culling each of the three vertices of the triangle to be rendered must be in the same space (World space) as the camera in order to perform the "winding" calculation. Therefore, at the start of the VU code loop, each vertex is transformed from local to world space using the World transformation matrix, then stored in a temporary register so that they are available for the culling calculation. This is achieved with the following micro-code.

 

 

; Transform the vertex by the World matrix (this is a macro from vcl_sml.i)

MatrixMultiplyVertex Vert, fWorld, Vert
 

; Store the vertex position in the temporary vertex buffer

; We use this for back face culling later

sq Vert, VertexBuffer(iVert)

 

 

Once all three triangle vertices have been transformed and stored, the back face culling calculation can be performed. This is achieved using the VU micro code below. Firstly the triangle vertices are read from the buffer into floating point registered. The TriangleWinding macro is then executed with the output "result" being non-zero if the winding is clockwise.

 

If the "result" is non-zero the back face culling code is executed. For the purpose of this illustration, all three vertex colours are set to white, but in reality the ADC bit of each vertex would be set to 1 (to not draw the vertex): note that this code is commented out in the listing below.

 

If the "result" is zero the triangle is drawn unmodified.

 

 

;--------------------------------

;Back Face Culling (Per Triangle)

;--------------------------------

 

; Read our buffered vertex positions

lq    Vertex1,  2+VertexBuffer(vi00)

lq    Vertex2,  1+VertexBuffer(vi00)

lq    Vertex3,  0+VertexBuffer(vi00)

 

; if vi01 = 1, our face needs to be culled

TriangleWinding Result, Vertex1, Vertex2, Vertex3, fCameraPos

 

ibeq    Result, vi00, Draw

                           

; Cull the triangle here

; Note that in this case we don't use this cull code

;isw.w    iADCNoDraw, StartVert(vi00)

;isw.w    iADCNoDraw, StartVert+2(vi00)

;isw.w    iADCNoDraw, StartVert+4(vi00)

 

; In our case we just set the vertex colour to white

sq            Colour, StartVert-1(vi00)

sq            Colour, StartVert+1(vi00)

sq            Colour, StartVert+3(vi00)

 

b    End_Cull

 

Draw:

 

; Set the ADC bit to 0 to draw vertex

isw.w    iADCDraw, StartVert+0(vi00)

isw.w    iADCDraw, StartVert+2(vi00)

isw.w    iADCDraw, StartVert+4(vi00)

 

End_Cull:

;----------------------------------------

  

 

The Example Application

 

In the example application a rotating triangle is shown on screen. When the front face of the triangle is facing the camera it is drawn with each vertex having a different colour. When the back face of the triangle is facing the camera it is drawn with all vertices being white.

 

 

Conclusions

 

This tutorial introduces a technique that can be used for back face culling within the graphics pipeline. As written the code is skeletal in nature and would need adaptation in order to incorporate the technique into a realistic application.

 

 

 

Dr Henry S Fortuna

University of Abertay Dundee

h.s.fortuna@abertay.ac.uk