/*---------------------------------------------------------------------------* Project: Dolphin/Revolution gx demo File: pix-sub.c Copyright 1998-2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* pix-sub Shadow volume algorithm by pixel subtract mode *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* Header files *---------------------------------------------------------------------------*/ #include #include /*---------------------------------------------------------------------------* Macro definitions *---------------------------------------------------------------------------*/ #define PI 3.14159265358979323846F #define MAX_Z 0x00ffffff // max value of Z buffer #define NUM_GRIDS 2 #define NUM_BALLS 8 #define BALL_RD 150.0F #define BALL_ORBIT 450.0F #define SCREEN_WD 640 #define SCREEN_HT 480 #define Clamp(val,min,max) \ ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))) /*---------------------------------------------------------------------------* Structure definitions *---------------------------------------------------------------------------*/ // for camera typedef struct { Vec location; Vec up; Vec target; f32 left; f32 top; f32 znear; f32 zfar; } CameraConfig; typedef struct { CameraConfig cfg; Mtx view; Mtx44 proj; s32 theta; s32 phi; f32 distance; } MyCameraObj; // for light typedef struct { GXLightObj lobj; MyCameraObj cam; } MyLightObj; // for entire scene control typedef struct { MyCameraObj cam; MyLightObj light; GXTexObj shadowTex; u8* shadowTexData; s32 modelRotZ; s32 modelRotY; Vec ballPos[NUM_BALLS]; u32 anim; } MySceneCtrlObj; /*---------------------------------------------------------------------------* Forward references *---------------------------------------------------------------------------*/ void main ( void ); static void DrawInit ( MySceneCtrlObj* sc ); static void DrawShutDown ( MySceneCtrlObj* sc ); static void DrawTick ( MySceneCtrlObj* sc ); static void AnimTick ( MySceneCtrlObj* sc ); static void DrawBalls ( MySceneCtrlObj* sc ); static void DrawShadowVol ( MySceneCtrlObj* sc ); static void DrawFloor ( void ); static void DrawScrSizeQuad ( void ); static void SetCamera ( MyCameraObj* cam ); static void SetLight ( MyLightObj* light, Mtx v ); static void DisableLight ( void ); static void PrintIntro ( void ); /*---------------------------------------------------------------------------* Lighting parameters *---------------------------------------------------------------------------*/ #define COL_WHITE MyColors[0] #define COL_BG MyColors[1] #define COL_AMBIENT MyColors[2] #define COL_LIGHT MyColors[3] #define COL_SHADOW MyColors[4] #define COL_BALLS MyColors[5] #define COL_FLOOR MyColors[6] static GXColor MyColors[] ATTRIBUTE_ALIGN(32) = { {0xff, 0xff, 0xff, 0xff}, // white {0x20, 0x20, 0x20, 0x00}, // background {0x40, 0x40, 0x40, 0xff}, // ambient {0xc0, 0xc0, 0xc0, 0xff}, // light color {0xa0, 0xa0, 0xa0, 0xff}, // shadow strength {0x80, 0xff, 0x60, 0xff}, // balls {0xf0, 0xf0, 0xf0, 0xff} // floor }; // fixed normal vector static f32 FixedNormal[] ATTRIBUTE_ALIGN(32) = { 1.0F, 0.0F, 0.0F, // X 0.0F, 1.0F, 0.0F, // Y 0.0F, 0.0F, 1.0F // Z }; /*---------------------------------------------------------------------------* Camera configuration *---------------------------------------------------------------------------*/ static CameraConfig DefaultCamera = { { 1500.0F, 1500.0F, 400.0F }, // location { 0.0F, 0.0F, 1.0F }, // up : { 0.0F, 0.0F, 0.0F }, // target -160.0F, // left 120.0F, // top 300.0F, // near 5000.0F // far }; static CameraConfig DefaultLightCamera = { { 1500.0F, 1500.0F, 2000.0F }, // location { 0.0F, 0.0F, 1.0F }, // up : { 0.0F, 0.0F, 400.0F }, // target -32.0F, // left 32.0F, // top 150.0F, // near 10000.0F // far }; /*---------------------------------------------------------------------------* Global Variables *---------------------------------------------------------------------------*/ static MySceneCtrlObj SceneCtrl; // scene control parameters static Vec DefaultBallPos[NUM_BALLS]; static TPLPalettePtr MyTplObj = NULL; static GXTexObj MyFloorTexObj; /*---------------------------------------------------------------------------* Application main loop *---------------------------------------------------------------------------*/ void main ( void ) { DEMOInit(&GXNtsc480IntDf); // Init the OS, game pad, graphics and video. DrawInit(&SceneCtrl); // Initialize vertex formats and scene parameters etc. PrintIntro(); // Print demo directions while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU)) { DEMOBeforeRender(); DrawTick(&SceneCtrl); // Draw the model. DEMODoneRender(); DEMOPadRead(); AnimTick(&SceneCtrl); // Update animation. } DrawShutDown(&SceneCtrl); OSHalt("End of demo"); } /*---------------------------------------------------------------------------* Functions *---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------* Name: DrawInit Description: Initializes the vertex attribute format, texture and default scene parameters. Arguments: sc : pointer to the structure of scene control parameters Returns: none *---------------------------------------------------------------------------*/ static void DrawInit( MySceneCtrlObj* sc ) { u32 size, i, deg; // set up a vertex attribute GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_S8, 4); GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_S8, 4); // Set pixel format with alpha GXSetPixelFmt(GX_PF_RGBA6_Z24, GX_ZC_LINEAR); GXSetCopyClear(COL_BG, MAX_Z); GXSetCullMode(GX_CULL_NONE); // Need to clear background by specified color // since pixelfmt is different than DEMOInit default. // The clear operation can be done by dummy copy. GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE); // Texture object for the floor TPLGetPalette(&MyTplObj, "gxTextrs.tpl"); TPLGetGXTexObjFromPalette(MyTplObj, &MyFloorTexObj, 6); // Default scene parameter settings // camera sc->cam.cfg = DefaultCamera; sc->cam.theta = 45; sc->cam.phi = 25; sc->cam.distance = 2500.0F; // light projection camera sc->light.cam.cfg = DefaultLightCamera; sc->light.cam.theta = 0; sc->light.cam.phi = 85; sc->light.cam.distance = 8000.0F; // model control parameters sc->modelRotZ = 0; sc->modelRotY = 0; sc->anim = 1; for ( i = 0 ; i < NUM_BALLS ; ++i ) { deg = 360 * i / NUM_BALLS; DefaultBallPos[i].x = cosf(MTXDegToRad(deg)) * BALL_ORBIT; DefaultBallPos[i].y = sinf(MTXDegToRad(deg)) * BALL_ORBIT; DefaultBallPos[i].z = 0.0F; } // Texture object for shadow size = GXGetTexBufferSize(SCREEN_WD, SCREEN_HT, GX_TF_I8, GX_FALSE, 0); sc->shadowTexData = MEMAllocFromAllocator(&DemoAllocator1, size); GXInitTexObj( &sc->shadowTex, sc->shadowTexData, SCREEN_WD, SCREEN_HT, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE ); GXInitTexObjLOD( &sc->shadowTex, GX_NEAR, GX_NEAR, 0.0F, 0.0F, 0.0F, GX_FALSE, GX_FALSE, GX_ANISO_1 ); } // Function for shutdown static void DrawShutDown( MySceneCtrlObj* sc ) { if ( sc->shadowTexData ) { MEMFreeToAllocator(&DemoAllocator1, sc->shadowTexData); sc->shadowTexData = NULL; } } /*---------------------------------------------------------------------------* Name: DrawTick Description: Draw the model by using given scene parameters Arguments: sc : pointer to the structure of scene control parameters Returns: none *---------------------------------------------------------------------------*/ // Set Color/Alpha/Z update control inline void SetCAZUpdate( GXBool cu, GXBool au, GXBool zc, GXBool zu ) { GXSetColorUpdate(cu); GXSetAlphaUpdate(au); GXSetZMode(zc, GX_LEQUAL, zu); } /*---------------------------------------------------------------------------*/ static void DrawTick( MySceneCtrlObj* sc ) { Mtx ms, mt, mv, mvi; f32 tr; GXInvalidateTexAll(); GXSetViewport(0, 0, SCREEN_WD, SCREEN_HT, 0.0F, 1.0F); //------------------------------------------- // Background //------------------------------------------- // culling/blending off GXSetCullMode(GX_CULL_BACK); GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_NOOP); // Color update ON, Alpha update OFF, Z update ON SetCAZUpdate(GX_ENABLE, GX_DISABLE, GX_ENABLE, GX_ENABLE); // Set camera for the main image SetCamera(&sc->cam); // Background floor GXSetNumTevStages(1); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); GXSetNumTexGens(1); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); SetLight(&sc->light, sc->cam.view); // Textures for floor panels GXLoadTexObj(&MyFloorTexObj, GX_TEXMAP0); GXSetChanMatColor(GX_COLOR0A0, COL_FLOOR); // Modelview matrix for floor panels tr = -(f32)NUM_GRIDS / 2.0F; MTXScale(ms, 800.0F, 800.0F, 100.0F); MTXTrans(mt, tr, tr, -3.5F); MTXConcat(ms, mt, ms); MTXConcat(sc->cam.view, ms, mv); GXLoadPosMtxImm(mv, GX_PNMTX0); MTXInvXpose(mv, mvi); GXLoadNrmMtxImm(mvi, GX_PNMTX0); // Draw floor panels DrawFloor(); //------------------------------------------- // Shadow volume #1 (front faces) //------------------------------------------- // Back-face culling, additive blend mode GXSetCullMode(GX_CULL_BACK); GXSetBlendMode(GX_BM_BLEND, GX_BL_ONE, GX_BL_ONE, GX_LO_NOOP); // Color update OFF, Alpha update ON, Z compare only SetCAZUpdate(GX_DISABLE, GX_ENABLE, GX_ENABLE, GX_DISABLE); // Set tev to use only one vertex color GXSetNumChans(1); GXSetNumTevStages(1); GXSetNumTexGens(0); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); DisableLight(); // shadow volume value (minimum unit for 6bit alpha plane) GXSetChanMatColor(GX_COLOR0A0, (GXColor){ 0x04, 0x04, 0x04, 0x04 }); DrawShadowVol(sc); //------------------------------------------- // Shadow volume #2 (back faces) //------------------------------------------- // Front-face culling, subtractive blend mode GXSetCullMode(GX_CULL_FRONT); GXSetBlendMode(GX_BM_SUBTRACT, GX_BL_ONE, GX_BL_ONE, GX_LO_NOOP); // Color update OFF, Alpha update ON, Z compare only SetCAZUpdate(GX_DISABLE, GX_ENABLE, GX_ENABLE, GX_DISABLE); // Set tev to use only one vertex color GXSetNumChans(1); GXSetNumTevStages(1); GXSetNumTexGens(0); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); DisableLight(); // shadow volume value (minimum unit for 6bit alpha plane) GXSetChanMatColor(GX_COLOR0A0, (GXColor){ 0x04, 0x04, 0x04, 0x04 }); DrawShadowVol(sc); //------------------------------------------- // Copy alpha plane image into Texture //------------------------------------------- // Copy shadow image into texture GXSetTexCopySrc(0, 0, SCREEN_WD, SCREEN_HT); GXSetTexCopyDst(SCREEN_WD, SCREEN_HT, GX_CTF_A8, GX_FALSE); // Clear alpha plane only // Color update OFF, Alpha update ON, Z update OFF SetCAZUpdate(GX_DISABLE, GX_ENABLE, GX_DISABLE, GX_DISABLE); GXCopyTex(sc->shadowTexData, GX_TRUE); // Wait for finishing the copy task in the graphics pipeline GXPixModeSync(); //------------------------------------------- // Draw shadows by using alpha texture //------------------------------------------- GXSetCullMode(GX_CULL_NONE); // Perform source color * destination color GXSetBlendMode(GX_BM_BLEND, GX_BL_ZERO, GX_BL_SRCCLR, GX_LO_NOOP); // Color update ON, Alpha update OFF, Z compare/update OFF SetCAZUpdate(GX_ENABLE, GX_DISABLE, GX_DISABLE, GX_DISABLE); GXSetNumTevStages(1); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_COMP_RGB8_EQ, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_ZERO, GX_CC_ONE, GX_CC_C0); GXSetTevColor(GX_TEVREG0, COL_SHADOW); // shadow strength GXSetNumTexGens(1); GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); DisableLight(); GXLoadTexObj(&sc->shadowTex, GX_TEXMAP0); DrawScrSizeQuad(); //------------------------------------------- // Foreground //------------------------------------------- // Shadows don't affect objects drawn below // culling/blending off GXSetCullMode(GX_CULL_BACK); GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_NOOP); // Color update ON, Alpha update OFF, Z compare/update ON SetCAZUpdate(GX_ENABLE, GX_DISABLE, GX_ENABLE, GX_ENABLE); // Set camera for the main image SetCamera(&sc->cam); // Balls GXSetNumChans(1); GXSetNumTevStages(1); GXSetNumTexGens(0); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR); SetLight(&sc->light, sc->cam.view); GXSetChanMatColor(GX_COLOR0A0, COL_BALLS); DrawBalls(sc); } /*---------------------------------------------------------------------------* Name: AnimTick Description: Changes scene parameters according to the pad status. Arguments: sc : pointer to the structure of scene control parameters Returns: none *---------------------------------------------------------------------------*/ static void AnimTick( MySceneCtrlObj* sc ) { f32 dy; Mtx mrz, mry, mt; // Camera position sc->cam.theta += ( DEMOPadGetStickX(0) / 24 ); Clamp(sc->cam.theta, 0, 90); sc->cam.phi += ( DEMOPadGetStickY(0) / 24 ); Clamp(sc->cam.phi, 5, 75); // Moves models automatically if (sc->anim) { sc->modelRotZ += 4; if ( sc->modelRotZ > 360 ) { sc->modelRotZ -= 360; } ++sc->modelRotY; if ( sc->modelRotY > 1400 ) { sc->modelRotY -= 1400; } } if ( DEMOPadGetButtonDown(0) & PAD_BUTTON_A ) { sc->anim = 1 - sc->anim; } // Ball animation dy = fabsf((f32)(sc->modelRotY - 700) / 10.0F); MTXRotDeg(mrz, 'Z', sc->modelRotZ); MTXRotDeg(mry, 'Y', dy); MTXConcat(mrz, mry, mt); MTXTransApply(mt, mt, 0.0F, 0.0F, 450.0F); MTXMultVecArray(mt, &DefaultBallPos[0], &sc->ballPos[0], NUM_BALLS); } /*---------------------------------------------------------------------------* Name: DrawBalls Description: Draws ball objects Arguments: sc : pointer to the structure of scene control parameters Returns: none *---------------------------------------------------------------------------*/ static void DrawBalls( MySceneCtrlObj* sc ) { u32 i; Mtx ms, mt, mv, mvi; GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_NRM, GX_DIRECT); MTXScale(ms, BALL_RD, BALL_RD, BALL_RD); for ( i = 0 ; i < NUM_BALLS ; ++i ) { MTXTransApply(ms, mt, sc->ballPos[i].x, sc->ballPos[i].y, sc->ballPos[i].z); MTXConcat(sc->cam.view, mt, mv); GXLoadPosMtxImm(mv, GX_PNMTX0); MTXInvXpose(mv, mvi); GXLoadNrmMtxImm(mvi, GX_PNMTX0); GXDrawSphere(12,16); } } /*---------------------------------------------------------------------------* Name: DrawShadowVol Description: Draws objects for shadow volumes Arguments: sc : pointer to the structure of scene control parameters Returns: none *---------------------------------------------------------------------------*/ static void DrawShadowVol( MySceneCtrlObj* sc ) { u32 i; Mtx ms, mt, mv; f32 zscale, zcenter; GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_NRM, GX_DIRECT); for ( i = 0 ; i < NUM_BALLS ; ++i ) { zscale = (sc->ballPos[i].z + 400.0F) / 2.0F; zcenter = (sc->ballPos[i].z - 400.0F) / 2.0F; MTXScale(ms, BALL_RD, BALL_RD, zscale); MTXTransApply(ms, mt, sc->ballPos[i].x, sc->ballPos[i].y, zcenter); MTXConcat(sc->cam.view, mt, mv); GXLoadPosMtxImm(mv, GX_PNMTX0); GXDrawCylinder(16); } } /*---------------------------------------------------------------------------* Name: DrawFloor Description: Draws the floor which contains some steps Arguments: none Returns: none *---------------------------------------------------------------------------*/ static void DrawFloor( void ) { s8 x, y, z; // set up vertex descriptors GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_NRM, GX_INDEX8); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); // normal array GXSetArray(GX_VA_NRM, FixedNormal, 3 * sizeof(f32)); z = 0; for ( y = 0 ; y < NUM_GRIDS ; ++y ) { GXBegin(GX_QUADS, GX_VTXFMT0, NUM_GRIDS * 12); for ( x = 0 ; x < NUM_GRIDS ; ++x ) { z = (s8)(NUM_GRIDS - x - y); // Z side GXPosition3s8(x, y, z); GXNormal1x8(2); GXTexCoord2s8(0, 0); GXPosition3s8(x, (s8)(y+1), z); GXNormal1x8(2); GXTexCoord2s8(0, 0x10); GXPosition3s8((s8)(x+1), (s8)(y+1), z); GXNormal1x8(2); GXTexCoord2s8(0x10, 0x10); GXPosition3s8((s8)(x+1), y, z); GXNormal1x8(2); GXTexCoord2s8(0x10, 0); // X side GXPosition3s8((s8)(x+1), y, z); GXNormal1x8(0); GXTexCoord2s8(0, 0); GXPosition3s8((s8)(x+1), (s8)(y+1), z); GXNormal1x8(0); GXTexCoord2s8(0x10, 0); GXPosition3s8((s8)(x+1), (s8)(y+1), (s8)(z-1)); GXNormal1x8(0); GXTexCoord2s8(0x10, 0x8); GXPosition3s8((s8)(x+1), y, (s8)(z-1)); GXNormal1x8(0); GXTexCoord2s8(0, 0x8); // Y side GXPosition3s8((s8)(x+1), (s8)(y+1), z); GXNormal1x8(1); GXTexCoord2s8(0, 0); GXPosition3s8(x, (s8)(y+1), z); GXNormal1x8(1); GXTexCoord2s8(0x10, 0); GXPosition3s8(x, (s8)(y+1), (s8)(z-1)); GXNormal1x8(1); GXTexCoord2s8(0x10, 0x8); GXPosition3s8((s8)(x+1), (s8)(y+1), (s8)(z-1)); GXNormal1x8(1); GXTexCoord2s8(0, 0x8); } GXEnd(); } } /*---------------------------------------------------------------------------* Name: DrawScrSizeQuad Description: Draws a full-screen size quad Arguments: none Returns: none *---------------------------------------------------------------------------*/ static void DrawScrSizeQuad( void ) { Mtx44 proj; Mtx mv; MTXOrtho(proj, 0, 480, 0, 640, 0.0F, 10000.0F); GXSetProjection(proj, GX_ORTHOGRAPHIC); MTXIdentity(mv); GXLoadPosMtxImm(mv, GX_PNMTX0); // set up vertex descriptors GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); GXBegin(GX_QUADS, GX_VTXFMT1, 4); GXPosition3s16( 0, 0, 0); GXTexCoord2s8(0x00, 0x00); GXPosition3s16(640, 0, 0); GXTexCoord2s8(0x10, 0x00); GXPosition3s16(640, 480, 0); GXTexCoord2s8(0x10, 0x10); GXPosition3s16( 0, 480, 0); GXTexCoord2s8(0x00, 0x10); GXEnd(); } /*---------------------------------------------------------------------------* Name: SetCamera Description: set view matrix and load projection matrix into hardware Arguments: cam : pointer to the MyCameraObj structure Returns: none *---------------------------------------------------------------------------*/ static void SetCamera( MyCameraObj* cam ) { f32 r_theta, r_phi; r_theta = (f32)cam->theta * PI / 180.0F; r_phi = (f32)cam->phi * PI / 180.0F; cam->cfg.location.x = cam->distance * cosf(r_theta) * cosf(r_phi); cam->cfg.location.y = cam->distance * sinf(r_theta) * cosf(r_phi); cam->cfg.location.z = cam->distance * sinf(r_phi); MTXLookAt( cam->view, &cam->cfg.location, &cam->cfg.up, &cam->cfg.target ); MTXFrustum( cam->proj, cam->cfg.top, - (cam->cfg.top), cam->cfg.left, - (cam->cfg.left), cam->cfg.znear, cam->cfg.zfar ); GXSetProjection(cam->proj, GX_PERSPECTIVE); } /*---------------------------------------------------------------------------* Name: SetLight Description: Set up lights and lighting channel parameters Arguments: light: pointer to a MyLightObj structure v: view matrix Returns: none *---------------------------------------------------------------------------*/ void SetLight( MyLightObj* light, Mtx v ) { Vec lpos = light->cam.cfg.location; // Multiplied by view matrix MTXMultVec(v, &lpos, &lpos); GXInitLightPos(&light->lobj, lpos.x, lpos.y, lpos.z); GXInitLightColor(&light->lobj, COL_LIGHT); GXLoadLightObjImm(&light->lobj, GX_LIGHT0); GXSetChanCtrl( GX_COLOR0A0, GX_ENABLE, // enable channel GX_SRC_REG, // amb source GX_SRC_REG, // mat source GX_LIGHT0, // light mask GX_DF_CLAMP, // diffuse function GX_AF_NONE ); // set up material color GXSetChanAmbColor(GX_COLOR0A0, COL_AMBIENT); } /*---------------------------------------------------------------------------* Name: DisableLight Description: Disables lighting Arguments: none Returns: none *---------------------------------------------------------------------------*/ void DisableLight( void ) { GXSetChanCtrl( GX_COLOR0A0, GX_DISABLE, // disable channel GX_SRC_REG, // amb source GX_SRC_REG, // mat source GX_LIGHT0, // light mask GX_DF_NONE, // diffuse function GX_AF_NONE); } /*---------------------------------------------------------------------------* Name: PrintIntro Description: Prints the directions on how to use this demo. Arguments: none Returns: none *---------------------------------------------------------------------------*/ static void PrintIntro( void ) { OSReport("\n\n"); OSReport("******************************************************\n"); OSReport("pix-sub: shadow volume demo by pixel subtract mode\n"); OSReport("******************************************************\n"); OSReport("to quit hit the start button\n"); OSReport("\n"); OSReport("Main stick : Move the camera\n"); OSReport("A Button : Stop/Start animation\n"); OSReport("******************************************************\n"); OSReport("\n\n"); } /*============================================================================*/