RenderWare V2.1

Previous Page Index Next Page


Polyline callback example
Immediate mode 2-D rendering.
Immediate mode Z-Buffering
Immediate mode in 16 bit true color
Immediate mode texturing
Immediate mode perspectively correct texturing in 2-D
Immediate mode Z-Buffering in 2-D

Examples


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 luminance’s 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();
}