The following section describes some immediate mode rendering examples. These should demonstrate the practical application of immediate mode rendering.
Polyline callback example
The following example callback draws a polyline between all the vertices in a clump. This is achieved with the 'VERTEX' mode, whereby vertices within the clump are reference by index. The code assumes an 8 bit video mode with only the 8 bit luminance values being set.
Note that most of the defaults for the immediate structure apply -- that is no Z-Buffering, with the current material.
static void
ClumpDrawLines(RwClump *clump)
{
RwInt32 numvert;
RwInt32 i;
RwImmediate imm;
RwReal maxlum;
/* Find the
maximum luminance value */
RwGetDeviceInfo(rwMAXLUMINANCE, &maxlum,
sizeof(maxlum));
/* Set up
the immediate structure for drawing lines */
RwSetupImmediateLine(&imm);
/* 'VERTEX'
mode - use the vertices out of the clump */
RWSETIMMEDIATEVERTICES(imm);
/* The line
is light sampled as FACET so set the
polygons luminance */
RWSETIMMPOLYLUM(RWIMMPOLY(imm),REAL2FIX(maxlum));
/* Get the
number of vertices in the clump */
numvert =
RwGetClumpNumVertices(clump);
/* The
current material is being used for this immediate
rendering */
RwPushCurrentMaterial();
/* Use the
polygon luminance for lighting the line */
RwSetMaterialLightSampling(RwCurrentMaterial(), rwFACET);
/* For all
the vertices in the clump */
for
(i=1;i<numvert;i++)
{
/* Vertex 0 of the line is vertex i of the clump */
RWSETIMMVERTEXNO(RWIMMVERTEX(imm,0),i);
/* Vertex 1
of the line is vertex i+1 of the clump */
RWSETIMMVERTEXNO(RWIMMVERTEX(imm,1),i+1);
/* Render
the line */
RwRenderImmediateLine(&imm);
}
/* Pop the
current material */
RwPopCurrentMaterial();
}
The clump's callback is set to this function with:
RwSetClumpImmediateCallBack(clump,
ClumpDrawLines);
Immediate mode 2-D rendering.
When rendering in 2-D, RenderWare does not clip any geometry so specified. Therefore all objects so rendered must be entirely on screen; if not, there may be a crash.
The following example displays 100 random triangles.
void
RenderImmediate2D(RwCamera *cam)
{
RwImmediate imm;
RwReal maxlum;
RwRect rect;
RwInt32 i;
/*
Invalidate the viewport */
RwInvalidateCameraViewport(cam);
/* Find the
maximum luminance value */
RwGetDeviceInfo(rwMAXLUMINANCE, &maxlum,
sizeof(maxlum));
/* Get the
viewport size */
RwGetCameraViewport(cam, &rect.x, &rect.y,
&rect.w, &rect.h);
/* Get a
new material */
RwPushCurrentMaterial();
/* Start
using immediate mode */
RwImmediateBegin(NULL);
/* Setup
for a triangle render */
RwSetupImmediateTriangle(&imm);
/* Vertices
specified in world space */
RWSETIMMEDIATE2D(imm);
/* Use a
luminance of 1/4 the maximum luminance */
RWSETIMMPOLYLUM(RWIMMPOLY(imm),
REAL2FIX(RDiv(maxlum, CREAL(4))));
/* Facet
light sampling */
RwSetMaterialLightSampling(RwCurrentMaterial(), rwFACET);
/* Double
sided polys */
RwSetSurfaceMaterialModes(rwDOUBLE);
for
(i=0;i<100;i++)
{
/* Set the
vertices at random positions */
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,0),
INT2FIX(RwRandom()%rect.w));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,0),
INT2FIX(RwRandom()%rect.h));
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,1),
INT2FIX(RwRandom()%rect.w));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,1),
INT2FIX(RwRandom()%rect.h));
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,2),
INT2FIX(RwRandom()%rect.w));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,2),
INT2FIX(RwRandom()%rect.h));
/* Set the
triangle material to a random color */
RwSetMaterialColor(RwCurrentMaterial(),
RDiv(INT2REAL(RwRandom()&0xff), CREAL(0xff)),
RDiv(INT2REAL(RwRandom()&0xff), CREAL(0xff)),
RDiv(INT2REAL(RwRandom()&0xff), CREAL(0xff)));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
}
/* End of
immediate mode */
RwImmediateEnd();
/* Remove
material from the stack */
RwPopCurrentMaterial();
}
Immediate mode Z-Buffering
The following example displays three Z-Buffered triangles. The vertices are held in world co-ordinate space, and are transformed before rendering. This code should be called within the RwBeginCameraUpdate() and RwEndCameraUpdate() cliché.
For example
RwBeginCameraUpdate(cam,
NULL);
RwClearCameraViewport(cam);
/* Do the
immediate mode rendering */
RenderImmediateZBuffer(cam);
RwEndCameraUpdate(cam);
RwShowCameraImage(cam,
NULL);
This code assumes the use of an 8 bit video mode with only the 8 bit luminance being set.
void
RenderImmediateZBuffer(RwCamera *cam)
{
RwImmediate imm;
RwRect rect;
RwMaterial *mat;
RwReal maxlum;
/*
Invalidate the viewport image */
RwInvalidateCameraViewport(cam);
/* Get the
cameras size - for the Z-Buffer size */
RwGetCameraViewport(cam, &rect.x, &rect.y,
&rect.w, &rect.h);
rect.x = 0;
rect.y = 0;
/* Find the
maximum luminance value */
RwGetDeviceInfo(rwMAXLUMINANCE, &maxlum,
sizeof(maxlum));
/* Material
to use */
mat =
RwCreateMaterial();
/* Start
using immediate mode with Z-Buffered area
specified by rect */
RwImmediateBegin(&rect);
/* Setup
for a triangle render */
RwSetupImmediateTriangle(&imm);
/* Vertices
specified in world space */
RWSETIMMEDIATE3D(imm);
/* Perform
Z-Buffering */
RWSETIMMEDIATEZBUFFERON(imm);
/* Use the
material mat */
RWSETIMMEDIATEMATERIAL(imm, mat);
/* Use a
luminance of half the maximum luminance */
RWSETIMMPOLYLUM(RWIMMPOLY(imm),
REAL2FIX(RDiv(maxlum, CREAL(2))));
/* Facet
light sampling */
RwSetMaterialLightSampling(mat, rwFACET);
/* Set up
vertex 0 at (-1,-1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,0),CREAL(-1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,0),CREAL(-1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,0),CREAL(0));
/* Set up
vertex 1 at (1,-1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,1),CREAL(1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,1),CREAL(-1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,1),CREAL(0));
/* Set up
vertex 2 at (1,1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,2),CREAL(1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,2),CREAL(1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,2),CREAL(0));
/* Set the
triangle material to green */
RwSetMaterialColor(mat, CREAL(0),CREAL(1),CREAL(0));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
/* Set up
vertex 0 at (-1,-1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,0),CREAL(-1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,0),CREAL(-1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,0),CREAL(0));
/* Set up
vertex 1 at (1,1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,1),CREAL(1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,1),CREAL(1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,1),CREAL(0));
/* Set up
vertex 2 at (-1,1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,2),CREAL(-1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,2),CREAL(1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,2),CREAL(0));
/* Set the
materials color to blue */
RwSetMaterialColor(mat, CREAL(0),CREAL(0),CREAL(1));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
/* Set up
vertex 0 at (1,1,-1) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,0),CREAL(1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,0),CREAL(1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,0),CREAL(-1));
/* Set up
vertex 1 at (-1,0,1) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,1),CREAL(-1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,1),CREAL(0));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,1),CREAL(1));
/* Set up
vertex 2 at (1,-1,-1) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,2),CREAL(1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,2),CREAL(-1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,2),CREAL(-1));
/* Set the
materials color to red */
RwSetMaterialColor(mat, CREAL(1),CREAL(0),CREAL(0));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
/* End of
immediate mode */
RwImmediateEnd();
/* No
longer need the material */
RwDestroyMaterial(mat);
}
If Z-Buffering had not been required then the RwImmediateBegin() should have been passed NULL. If Z-Buffering were to have been activated or deactivated on a per polygon basis the RWSETIMMEDIATEZBUFFERON() macro should have been be used. Note that the Z-Buffer area must be specified in RwImmediateBegin(), if the Z-Buffering were ever switched on with this macro.
Immediate mode in 16 bit true color
The following example randomly changes the red, green and blue luminance channels at the vertices on a sphere. This demo should only be run in 16 bit; in 8 bit, the brightness of the polygon will change with the red component since in 8 bit this is the only active channel for lighting.
The following code section is the callback function
static void
ClumpCallBack(RwClump *clump)
{
int numvert;
int i;
RwReal maxlum;
RwReal rate;
RwImmVertex3d *vertex;
RwReal red, green, blue;
RwInt32 random;
/* Get the
maximum luminance value for the device */
RwGetDeviceInfo(rwMAXLUMINANCE, &maxlum,
sizeof(maxlum));
rate =
RDiv(maxlum, CREAL(50));
/* Specify
position by vertices */
numvert =
RwGetClumpNumVertices(clump);
for
(i=1;i<=numvert;i++)
{
vertex = RwGetClumpImmVertex(clump, i);
red =
FIX2REAL(RWGETIMMVERTEXRED(*vertex));
green = FIX2REAL(RWGETIMMVERTEXGREEN(*vertex));
blue = FIX2REAL(RWGETIMMVERTEXBLUE(*vertex));
random =
RwRandom();
/* Tweak
Red */
red +=
(random&1) ? (-rate) : rate;
red =(red > maxlum) ? maxlum : red;
red =(red < CREAL(0)) ? CREAL(0) : red;
/* Tweak
green */
green +=
(random&2) ? (-rate) : rate;
green =(green > maxlum) ? maxlum : green;
green =(green < CREAL(0)) ? CREAL(0) : green;
/* Tweak
blue */
blue +=
(random&4) ? (-rate) : rate;
blue =(blue > maxlum) ? maxlum : blue;
blue =(blue < CREAL(0)) ? CREAL(0) : blue;
/* Set the
luminance values */
RWSETIMMVERTEXRGB((*vertex), REAL2FIX(red),
REAL2FIX(green), REAL2FIX(blue));
}
RwRenderImmediateClump();
}
This code initialises the clump for rendering
{
RwClump *clump;
/* Create
the clump */
RwModelBegin();
RwClumpBegin();
RwSetSurfaceColor(CREAL(1), CREAL(1), CREAL(1));
RwSetSurfaceLightSampling(rwVERTEX);
RwSetSurfaceGeometrySampling(rwSOLID);
RwSetSurfaceTexture(NULL);
RwSetSurface(CREAL(0.4), CREAL(0.5), CREAL(0.3));
RwSphere(CREAL(1),5);
RwClumpEnd(&clump);
RwModelEnd();
/* Set the
clumps callback */
RwSetClumpImmediateCallBack(clump, ClumpCallBack);
/* Turn off
light sampling on the clump */
RwSetClumpLightSampleRate(clump, CREAL(0));
}
When the clump 'clump' is rendered, either as a result of being in a rendered a scene or by a direct call to RwRenderClump(), the clump's callback will be invoked. This will alter the vertex luminances of the sphere.
Immediate mode texturing
When texture mapping in immediate mode, U and V texture co-ordinates must be set at the vertices. The following code segment displays a perspectively correct texture mapped polygon. This function can only be safely called between RwBeginCameraUpdate() and RwEndCameraUpdate().
void
RenderImmediateTexture(RwCamera *cam)
{
RwImmediate imm;
RwMaterial *mat;
RwReal maxlum;
RwTexture *texture;
texture =
RwGetNamedTexture("hue");
/*
Invalidate the viewport image */
RwInvalidateCameraViewport(cam);
/* Get the
maximum luminance value */
RwGetDeviceInfo(rwMAXLUMINANCE, &maxlum,
sizeof(maxlum));
/* Material
to use */
mat =
RwCreateMaterial();
/* Start
using immediate mode with Z-Buffered area
specified by rect */
RwImmediateBegin(NULL);
/* Setup
for a triangle render */
RwSetupImmediateTriangle(&imm);
/* Vertices
specified in world space */
RWSETIMMEDIATE3D(imm);
/* Perform
Z-Buffering */
RWSETIMMEDIATEZBUFFEROFF(imm);
/* Use the
material mat */
RWSETIMMEDIATEMATERIAL(imm, mat);
/* Use a
luminance of half the maximum luminance */
RWSETIMMPOLYLUM(RWIMMPOLY(imm),
REAL2FIX(RDiv(maxlum, CREAL(2))));
/* Facet
light sampling */
RwSetMaterialLightSampling(mat, rwFACET);
/* Make the
polygon texture mapped */
RwSetMaterialTexture(mat, texture);
RwSetMaterialTextureModes(mat, rwFORESHORTEN);
/* Set up
vertex 0 at (-1,-1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,0), CREAL(-1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,0), CREAL(-1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,0), CREAL(0));
RWSETIMMVERTEXTEXUV(RWIMMVERTEX(imm,0), CFIX(0),
CFIX(0));
/* Set up
vertex 1 at (1,-1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,1), CREAL(1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,1), CREAL(-1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,1), CREAL(0));
RWSETIMMVERTEXTEXUV(RWIMMVERTEX(imm,1), CFIX(0),
CFIX(1));
/* Set up
vertex 2 at (1,1,0) */
RWSETIMMVERTEX3DX(RWIMMVERTEX(imm,2), CREAL(1));
RWSETIMMVERTEX3DY(RWIMMVERTEX(imm,2), CREAL(1));
RWSETIMMVERTEX3DZ(RWIMMVERTEX(imm,2), CREAL(0));
RWSETIMMVERTEXTEXUV(RWIMMVERTEX(imm,2), CFIX(1),
CFIX(0));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
/* End of
immediate mode */
RwImmediateEnd();
/* No
longer need the material */
RwDestroyMaterial(mat);
}
Immediate mode perspectively correct texturing in 2-D
When perspectively correct texture mapping with 2-D co-ordinates in immediate mode, additional information is required by the renderer. This information is
· The UV co-ordinates at each vertex
· The camera Z depth at each vertex
· The pixel Z depth at each vertex; this can be calculated by RwImmZBufferDepth() from the camera Z depth.
The following example draws a perspectively correct textured triangle with a 2-D vertex specification. This function can only be called between RwBeginCameraUpdate() and RwEndCameraUpdate().
void
RenderImmediatePerspectiveTexture2D(RwCamera *cam)
{
RwImmediate imm;
RwMaterial *mat;
RwReal maxlum;
RwTexture *texture;
texture =
RwGetNamedTexture("hue");
/*
Invalidate the viewport image */
RwInvalidateCameraViewport(cam);
/* Get the
maximum luminance value */
RwGetDeviceInfo(rwMAXLUMINANCE, &maxlum,
sizeof(maxlum));
/* Material
to use */
mat =
RwCreateMaterial();
/* Start
using immediate mode with Z-Buffered area
specified by rect */
RwImmediateBegin(NULL);
/* Setup
for a triangle render */
RwSetupImmediateTriangle(&imm);
/* Vertices
specified in world space */
RWSETIMMEDIATE2D(imm);
/* Perform
Z-Buffering */
RWSETIMMEDIATEZBUFFEROFF(imm);
/* Use the
material mat */
RWSETIMMEDIATEMATERIAL(imm, mat);
/* Use a
luminance of half the maximum luminance */
RWSETIMMPOLYLUM(RWIMMPOLY(imm),
REAL2FIX(RDiv(maxlum, CREAL(2))));
/* Facet
light sampling */
RwSetMaterialLightSampling(mat, rwFACET);
/* Make the
polygon texture mapped */
RwSetMaterialModes(mat, rwDOUBLE);
RwSetMaterialTexture(mat, texture);
RwSetMaterialTextureModes(mat, rwFORESHORTEN);
/* Set up
vertex 0 at (10,10) camera depth 2*/
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,0), CFIX(10));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,0), CFIX(10));
RWSETIMMVERTEX2DCAMERAZ(RWIMMVERTEX(imm,0), CREAL(2));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,0),
RwImmZBufferDepth(cam, CREAL(2)));
RWSETIMMVERTEXTEXUV(RWIMMVERTEX(imm,0), CFIX(0),
CFIX(0));
/* Set up
vertex 1 at (100,15) camera depth 3 */
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,1), CFIX(100));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,1), CFIX(15));
RWSETIMMVERTEX2DCAMERAZ(RWIMMVERTEX(imm,1), CREAL(3));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,1),
RwImmZBufferDepth(cam, CREAL(3)));
RWSETIMMVERTEXTEXUV(RWIMMVERTEX(imm,1),CFIX(0),CFIX(1));
/* Set up
vertex 2 at (50,100) camera depth 40 */
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,2), CFIX(50));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,2), CFIX(100));
RWSETIMMVERTEX2DCAMERAZ(RWIMMVERTEX(imm,2), CREAL(40));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,2),
RwImmZBufferDepth(cam, CREAL(40)));
RWSETIMMVERTEXTEXUV(RWIMMVERTEX(imm,2),CFIX(1),CFIX(0));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
/* End of
immediate mode */
RwImmediateEnd();
/* No
longer need the material */
RwDestroyMaterial(mat);
}
Immediate mode Z-Buffering in 2-D
When Z-Buffering in 2-D, the 2-D Z values of vertices must be set. The following example queried the Z-Buffer range and thus draws two intersecting (randomly colored) 2-D Z-Buffered triangles.
#define
TRI0_CAMERAZ_0 35
#define TRI0_CAMERAZ_1 30
#define TRI0_CAMERAZ_2 25
#define
TRI1_CAMERAZ_0 40
#define TRI1_CAMERAZ_1 30
#define TRI1_CAMERAZ_2 20
static void
RenderImmediate2DZBuffer(RwCamera *cam)
{
RwImmediate imm;
RwReal maxlum;
RwRect rect;
RwFixed maxz, minz;
RwReal zscale, zadd;
/* Get the
maximum and minimum Z values */
RwGetDeviceInfo(rwMAXZBUFFERZ, &maxz, sizeof(maxz));
RwGetDeviceInfo(rwMINZBUFFERZ, &minz, sizeof(minz));
zscale =
FIX2REAL(maxz - minz);
zadd = FIX2REAL(minz);
/*
Invalidate the viewport */
RwInvalidateCameraViewport(cam);
/* Find the
maximum luminance value */
RwGetDeviceInfo(rwMAXLUMINANCE, &maxlum,
sizeof(maxlum));
/* Get the
viewport size */
RwGetCameraViewport(cam, &rect.x, &rect.y,
&rect.w, &rect.h);
/* Get a
new material */
RwPushCurrentMaterial();
/* Start
using immediate mode - Set Z-Buffer rectangle */
RwImmediateBegin(&rect);
/* Setup
for a triangle render */
RwSetupImmediateTriangle(&imm);
/* Vertices
specified in world space */
RWSETIMMEDIATE2D(imm);
/* Turn on
Z-Buffering */
RWSETIMMEDIATEZBUFFERON(imm);
/* Use a
luminance of 1/4 the maximum luminance */
RWSETIMMPOLYRGB(RWIMMPOLY(imm),
REAL2FIX(RDiv(maxlum, CREAL(4))),
REAL2FIX(RDiv(maxlum, CREAL(4))),
REAL2FIX(RDiv(maxlum, CREAL(4))));
/* Facet
light sampling */
RwSetMaterialLightSampling(RwCurrentMaterial(),rwFACET);
/* Double
sided polys */
RwSetSurfaceMaterialModes(rwDOUBLE);
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,0), CFIX(10));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,0),CFIX(10));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,0),
REAL2FIX(RMul(CREAL(1.0/TRI0_CAMERAZ_0),
zscale) + zadd));
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,1),CFIX(100));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,1),CFIX(100));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,1),
REAL2FIX(RMul(CREAL(1.0/TRI0_CAMERAZ_1),zscale)+zadd));
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,2), CFIX(10));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,2),CFIX(190));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,2),
REAL2FIX(RMul(CREAL(1.0/TRI0_CAMERAZ_2),zscale) + zadd));
/* Set the
triangle material to a random color */
RwSetMaterialColor(RwCurrentMaterial(),
RDiv(INT2REAL(RwRandom()&0xff), CREAL(0xff)),
RDiv(INT2REAL(RwRandom()&0xff),CREAL(0xff)),
RDiv(INT2REAL(RwRandom()&0xff),CREAL(0xff)));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,0),CFIX(30));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,0),CFIX(110));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,0),
REAL2FIX(RMul(CREAL(1.0/TRI1_CAMERAZ_0), zscale)+ zadd));
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,1), CFIX(80));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,1), CFIX(20));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,1),
REAL2FIX(RMul(CREAL(1.0/TRI1_CAMERAZ_1), zscale)+ zadd));
RWSETIMMVERTEX2DX(RWIMMVERTEX(imm,2), CFIX(90));
RWSETIMMVERTEX2DY(RWIMMVERTEX(imm,2), CFIX(180));
RWSETIMMVERTEX2DZ(RWIMMVERTEX(imm,2),
REAL2FIX(RMul(CREAL(1.0/TRI1_CAMERAZ_2), zscale)+ zadd));
/* Set the
triangle material to a random color */
RwSetMaterialColor(RwCurrentMaterial(),
RDiv(INT2REAL(RwRandom()&0xff),CREAL(0xff)),
RDiv(INT2REAL(RwRandom()&0xff),CREAL(0xff)),
RDiv(INT2REAL(RwRandom()&0xff),CREAL(0xff)));
/* Render
the triangle */
RwRenderImmediateTriangle(&imm);
/* End of
immediate mode */
RwImmediateEnd();
/* Remove
material from the stack */
RwPopCurrentMaterial();
}