PS2 Linux Programming
Ambient Light and 3 Directional Coloured lights
Introduction
This tutorial demonstrates rendering using 3 directional light sources and ambient light. Each directional light source has colour and direction and the ambient light source has colour. The light source calculations are undertaken by VU1.
Background
Light source calculations are used to determine the contribution at the vertex of each light source within a virtual world. The vertex normal determines the orientation of the vertex, and hence the contribution that each light source makes when determining the illumination level of the vertex.
The following information is required in order to perform light source calculations:
(Nx, Ny, Nz) The vertex normal in local space.
(Lx, Ly, Lz) The light source direction vector.
(Lr, Lg, Lb) The light source colour intensities.
(Ar, Ag, Ab) The background ambient light intensities.
Firstly it is necessary to convert the normal vectors from local model space to world space. This is required because the light direction vectors are defined in world space, whereas the model normals are in local space. The conversion is achieved by multiplying the vertex normals by the world matrix for the model being drawn.
(NWx, NWy, NWz) is the vertex normals in world space. Notice that the vertex normals must only be transformed by the rotation components of the world transformations matrix since only the orientation of the normals need to be altered. Including the translation components within the matrix will provide the wrong result. In practice , it is only necessary to send the rotation parts of the world transformation matrix to the VU for processing the normals.
Next the dot product must be obtained between the vertex normal and the light source direction to obtain the influence of the light source on the vertex. This can be accomplished in matrix form for all three light sources as shown below. Note that it is necessary to reverse the direction of the light vectors prior to performing the dot product.
LI1, LI2 and LI3 are the influence that each of the light sources make on the vertex.
Next the light source influence colour is obtained. The light source influence colour is the contribution that each light source makes to the final colour of the vertex. Again, this can be accomplished in matrix form as shown below.
(LIr, LIg, LIb) is the total red, green and blue contributions from all of the three light sources. The final colour of the vertex is obtained by adding the ambient light intensity to the light source influence colour.
Where (R, G, B) is the final vertex colour.
Example Code
The layout of data in VU memory is shown below:
Address |
Data |
0 |
Transformation Matrix Row #0 |
1 |
Transformation Matrix Row #1 |
2 |
Transformation Matrix Row #2 |
3 |
Transformation Matrix Row #3 |
4 |
World Matrix Row #0 |
5 |
World Matrix Row #1 |
6 |
World Matrix Row #2 |
7 |
World Matrix Row #3 |
8 |
Scaling Vector (number of vertices in w) |
9 |
Directional Light Vector #1 (normalised) |
10 |
Directional Light Vector #2 (normalised) |
11 |
Directional Light Vector #3 (normalised) |
12 |
Light Colour #1 |
13 |
Light Colour #1 |
14 |
Light Colour #1 |
15 |
Ambient Light |
16 |
GIFTag |
17 |
Texture Coordinate (STQ) for Vertex #1 |
18 |
Normal for Vertex #1 |
19 |
Position for Vertex #1 |
20 |
Texture Coordinate (STQ) for Vertex #2 |
21 |
Normal for Vertex #2 |
22 |
Position for Vertex #2 |
23 |
Texture Coordinate (STQ) for Vertex #3 |
24 |
Normal for Vertex #3 |
25 |
Position for Vertex #3 |
etc |
etc |
VU1 Data Memory Layout
The lighting information is constructed using the following code:
// Set up 3 directional lights
Vector4 LightDir1( 1, 0, 0, 0);
Vector4 LightDir2(-1, 0, 0, 0);
Vector4 LightDir3( 0, 0, -1, 0);
// Then normalise.
LightDir1.NormaliseSelf();
LightDir2.NormaliseSelf();
LightDir3.NormaliseSelf();
// Light dir matrix (on VU1 we can do 3 lights + Ambient for the same price as 1)
VIFStaticDMA.AddVector(Vector4(LightDir1.x,LightDir2.x,LightDir3.x,0));
VIFStaticDMA.AddVector(Vector4(LightDir1.y,LightDir2.y,LightDir3.y,0));
VIFStaticDMA.AddVector(Vector4(LightDir1.z,LightDir2.z,LightDir3.z,0));
// Light colour matrix (3 directional light colours)
VIFStaticDMA.AddVector(Vector4(128, 0, 0, 0));
VIFStaticDMA.AddVector(Vector4(0 ,128, 0, 0));
VIFStaticDMA.AddVector(Vector4(0 , 0,128, 0));
// Ambient light colour
VIFStaticDMA.AddVector(Vector4( 10, 10, 10, 0));
Notice that the light direction vectors are normalised prior to being added to the static packet memory. Also note that the light direction vectors are in column major order. In this particular arrangement, there are three light sources, a red source is pointing in the x direction, a green source is pointing in the negative x direction and a blue source is pointing in the negative z directions. This arrangement is illustrated in pictorial form below.
The Vector Unit code which performs the lighting calculations is shown below.
;LIGHTING CALCULATIONS
lq.xyz Norm, StartNorm(iVertPtr) ; Load the normal
mul.xyz acc, fLightTrans[0], Norm[x] ; Transform by rotation part of the world matrix
madd.xyz acc, fLightTrans[1], Norm[y]
madd.xyz Norm, fLightTrans[2], Norm[z]
mula.xyz acc, fLightDirs[0], Norm[x] ; "Transform" normal by light direction matrix
madd.xyz acc, fLightDirs[1], Norm[y] ; This has the effect of outputting a vector with
madd.xyz fIntensities, fLightDirs[2], Norm[z] ; three intensities, one for each light.
mini.xyz fIntensities, fIntensities, vf00[w] ; Clamp the intensity to 0..1
max.xyz fIntensities, fIntensities, vf00[x]
mula.xyz acc, fLightCols[0], fIntensities[x] ; Transform intensities by light colour matrix
madda.xyz acc, fLightCols[1], fIntensities[y] ; This gives total directional light colour
madda.xyz acc, fLightCols[2], fIntensities[z]
madd.xyz fIntensities, fAmbient, vf00[w]
addi.w fIntensities, vf00, i ; Store the alpha value
ftoi0 fIntensities, fIntensities ; Convert to int
sq fIntensities, StartNorm(iVertPtr) ; And write to the output buffer
;END LIGHTING CALCULATIONS
It can be seen that the vector unit code follows exactly the algorithms presented above.
Sample Application
The sample application shows a rotating textured cube illuminated by the three directional lights and ambient light. As the cube rotates, the effect of the red light shining from the left, the green light from the right and the blue light from the direction of the viewer can be seen. It is possible to rotate the cube around the origin using the left and right directions buttons, and the camera can be moved around as in the previous applications using the analogue skicks.
Conclusions
This tutorial has provided background on the use of directional coloured lighting and has illustrated the techniques in the sample application.
Dr Henry S Fortuna
University of Abertay Dundee