1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tg-shadow2.c
4 
5   Copyright 1998 - 2006 Nintendo.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 /*---------------------------------------------------------------------------*
14    tg-shadow2
15      Full-scene shadow method by object ID map
16  *---------------------------------------------------------------------------*
17 
18    Overview of this method:
19 
20        (1st. pass) Render the entire scene from the light's point
21        of view. At this time, paint each object by its individual
22        ID number (as gray scale value of the color).
23 
24        Then copy the result framebuffer into a texture (shadow ID map).
25        The framebuffer is cleared at the same time.
26 
27        (2nd. pass) Render the entire scene viewed from the camera.
28        Then load the shadow ID map and apply texture coord projection
29        from the light. Compare the ID number of the object to be
30        drawn and that from projected shadow map. If two ID numbers
31        are not similar, it means a ray from the light is obstructed
32        by an another polygon which contains another ID. So the part
33        should become shadow. The comparison is done by some TEV
34        stages where ID values are considered as color data.
35 
36  *---------------------------------------------------------------------------*/
37 
38 /*---------------------------------------------------------------------------*
39    Header files
40  *---------------------------------------------------------------------------*/
41 #include <demo.h>
42 #include <math.h>
43 
44 /*---------------------------------------------------------------------------*
45    Macro definitions
46  *---------------------------------------------------------------------------*/
47 #define PI                  3.14159265358979323846F
48 #define MAX_Z               0x00ffffff // max value of Z buffer
49 
50 #define NUM_SHADOW_SIZES    4
51 #define SHADOW_TEX_MAX      480
52 
53 #define SHADOW_TEX_FMT      GX_TF_I8
54 #define SHADOW_TEX_CPFMT    GX_CTF_R8
55 
56 
57 #define NUM_DISP_MODES      3
58 
59 // default parameters for animating object
60 #define BALL_VX_INI         15.0F
61 #define BALL_VZ_INI         25.0F
62 
63 
64 #define Clamp(val,min,max) \
65     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
66 
67 /*---------------------------------------------------------------------------*
68   Structure definitions
69  *---------------------------------------------------------------------------*/
70 // for camera
71 typedef struct
72 {
73     Vec               location;
74     Vec               up;
75     Vec               target;
76     f32               left;
77     f32               top;
78     f32               znear;
79     f32               zfar;
80     GXProjectionType  type;
81 } CameraConfig;
82 
83 typedef struct
84 {
85     CameraConfig      cfg;
86     Mtx               view;
87     Mtx44             proj;
88     s32               theta;
89     s32               phi;
90     f32               distance;
91 } MyCameraObj;
92 
93 // for light
94 typedef struct
95 {
96     GXLightObj    lobj;
97     MyCameraObj   cam;  // for projection
98 } MyLightObj;
99 
100 // for animating objects
101 typedef struct
102 {
103     u32           octaRot;
104     f32           ballX;
105     f32           ballZ;
106     f32           ballVx;
107     f32           ballVz;
108 } MyAnimCtrlObj;
109 
110 // for entire scene control
111 typedef struct
112 {
113     MyCameraObj   cam;
114     MyLightObj    light;
115     MyAnimCtrlObj anim;
116     u32           dispMode;
117     u32           projMode;
118     u32           adjMode;
119     u8*           shadowTexData;
120     u32           shadowTexSize;
121 } MySceneCtrlObj;
122 
123 /*---------------------------------------------------------------------------*
124    Forward references
125  *---------------------------------------------------------------------------*/
126 void        main            ( void );
127 static void DrawInit        ( MySceneCtrlObj* sc );
128 static void DrawTick        ( MySceneCtrlObj* sc );
129 static void AnimTick        ( MySceneCtrlObj* sc );
130 static void DrawModels      ( Mtx view, Mtx tgv, f32 adj, MyAnimCtrlObj* anim );
131 static void LoadGXMatrices  ( Mtx view, Mtx tgv, Mtx mdm );
132 static void GetTexProjMtx   ( MyCameraObj* cam, Mtx mp );
133 static void SetModelID      ( u8 id );
134 static void SetCamera       ( MyCameraObj* cam );
135 static void SetLight        ( MyLightObj* light, Mtx v );
136 
137 static void SetShaderModeFor1stPass  ( void );
138 static void SetShaderModeFor2ndPass  ( void );
139 static void SetShaderModeForProj     ( void );
140 
141 static void PrintIntro      ( void );
142 
143 /*---------------------------------------------------------------------------*
144    Lighting parameters
145  *---------------------------------------------------------------------------*/
146 #define COL_WHITE    MyColors[0]
147 #define COL_BLACK    MyColors[1]
148 #define COL_AMBIENT  MyColors[2]
149 #define COL_LIGHT    MyColors[3]
150 #define COL_MAT0     MyColors[4]
151 #define COL_SHADOW0  MyColors[5]
152 #define COL_MAT1     MyColors[6]
153 #define COL_SHADOW1  MyColors[7]
154 #define COL_MAT2     MyColors[8]
155 #define COL_SHADOW2  MyColors[9]
156 #define COL_MAT3     MyColors[10]
157 #define COL_SHADOW3  MyColors[11]
158 
159 static GXColor MyColors[] ATTRIBUTE_ALIGN(32) =
160 {
161     {0xff, 0xff, 0xff, 0xff},  // white
162     {0x00, 0x00, 0x00, 0x00},  // background
163     {0x40, 0x40, 0x40, 0xff},  // ambient
164     {0xb0, 0xb0, 0xb0, 0xff},  // light color
165     {0xf0, 0xf0, 0xf0, 0xff},  // material color 0
166     {0x3C, 0x3C, 0x3C, 0xff},  // shadow color 0
167     {0xff, 0xe0, 0x80, 0xff},  // material color 1
168     {0x40, 0x38, 0x20, 0xff},  // shadow color 1
169     {0x80, 0xff, 0x80, 0xff},  // material color 2
170     {0x20, 0x40, 0x20, 0xff},  // shadow color 2
171     {0xA0, 0xc0, 0xff, 0xff},  // material color 3
172     {0x28, 0x30, 0x40, 0xff},  // shadow color 3
173 };
174 
175 /*---------------------------------------------------------------------------*
176    Other table data
177  *---------------------------------------------------------------------------*/
178 // shadow map texture size
179 static u16 ShadowSizeTbl[NUM_SHADOW_SIZES] =
180 {
181     480, 256, 128, 64
182 };
183 
184 /*---------------------------------------------------------------------------*
185    Strings for messages
186  *---------------------------------------------------------------------------*/
187 static char* DispModeMsg[] =
188 {
189     "result scene",
190     "ID of each object",
191     "projected shadow (ID) map"
192 };
193 
194 static char* ProjModeMsg[] =
195 {
196     "Perspective",
197     "Orthographic"
198 };
199 
200 static char* AdjModeMsg[] =
201 {
202     "OFF",
203     "ON"
204 };
205 
206 /*---------------------------------------------------------------------------*
207    Camera configuration
208  *---------------------------------------------------------------------------*/
209 static CameraConfig DefaultCamera =
210 {
211     { 1.0F, 1.0F, 1.0F }, // location (Not used)
212     { 0.0F, 0.0F, 1.0F }, // up
213     { 0.0F, 0.0F, 0.0F }, // target
214     -160.0F,  // left
215     120.0F,   // top
216     300.0F,   // near
217     5000.0F,  // far
218     GX_PERSPECTIVE // type
219 };
220 
221 static CameraConfig DefaultLightCamera0 =
222 {
223     { 1.0F, 1.0F, 1.0F }, // location (Not used)
224     { 0.0F, 0.0F, 1.0F }, // up
225     { 0.0F, 0.0F, 0.0F }, // target
226     -64.0F,   // left
227      64.0F,   // top
228     200.0F,   // near
229     10000.0F, // far
230     GX_PERSPECTIVE // type
231 };
232 
233 static CameraConfig DefaultLightCamera1 =
234 {
235     { 1.0F, 1.0F, 1.0F }, // location (Not used)
236     { 0.0F, 0.0F, 1.0F }, // up
237     { 0.0F, 0.0F, 0.0F }, // target
238     -832.0F, // left
239      832.0F, // top
240     200.0F,   // near
241     10000.0F, // far
242     GX_ORTHOGRAPHIC // type
243 };
244 
245 /*---------------------------------------------------------------------------*
246    Global Variables
247  *---------------------------------------------------------------------------*/
248 static MySceneCtrlObj  SceneCtrl;    // scene control parameters
249 
250 /*---------------------------------------------------------------------------*
251    Application main loop
252  *---------------------------------------------------------------------------*/
main(void)253 void main ( void )
254 {
255     DEMOInit(NULL);       // Init the OS, game pad, graphics and video.
256 
257     DrawInit(&SceneCtrl); // Initialize vertex formats and scene parameters etc.
258 
259     PrintIntro();  // Print demo directions
260 
261     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
262     {
263         DEMOBeforeRender();
264         DrawTick(&SceneCtrl);    // Draw the model.
265         DEMODoneRender();
266         DEMOPadRead();
267         AnimTick(&SceneCtrl);    // Update animation.
268     }
269 
270     OSHalt("End of demo");
271 }
272 
273 /*---------------------------------------------------------------------------*
274    Functions
275  *---------------------------------------------------------------------------*/
276 /*---------------------------------------------------------------------------*
277     Name:           DrawInit
278 
279     Description:    Initializes the vertex attribute format, texture and
280                     default scene parameters.
281 
282     Arguments:      sc : pointer to the structure of scene control parameters
283 
284     Returns:        none
285  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)286 static void DrawInit( MySceneCtrlObj* sc )
287 {
288     u32    size;
289 
290     // Set pixel format and background color
291     GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
292     GXSetCopyClear(COL_BLACK, MAX_Z);
293     GXSetCullMode(GX_CULL_NONE);
294 
295     // Perform dummy copy to clear EFB by specified color
296     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
297 
298 
299     // Default scene parameter settings
300 
301     // camera
302     sc->cam.cfg      = DefaultCamera;
303     sc->cam.theta    = 45;
304     sc->cam.phi      = 25;
305     sc->cam.distance = 2000.0F;
306 
307     // Light camera
308     sc->projMode           = 0;
309     sc->light.cam.theta    = 0;
310     sc->light.cam.phi      = 60;
311     sc->light.cam.distance = 3000.0F;
312 
313     // display mode and shadow map control mode
314     sc->dispMode      = 0;
315     sc->shadowTexSize = 0;
316     sc->adjMode       = 1;
317 
318     // animating objects
319     sc->anim.octaRot = 0;
320     sc->anim.ballX   = 0.0F;
321     sc->anim.ballZ   = 0.0F;
322     sc->anim.ballVx  = BALL_VX_INI;
323     sc->anim.ballVz  = BALL_VZ_INI;
324 
325     // Memory area for dynamic shadow map
326     size = GXGetTexBufferSize(
327                SHADOW_TEX_MAX,
328                SHADOW_TEX_MAX,
329                SHADOW_TEX_FMT,
330                GX_FALSE,
331                0 );
332     sc->shadowTexData = MEMAllocFromAllocator(&DemoAllocator1, size);
333 
334 }
335 
336 /*---------------------------------------------------------------------------*
337     Name:           DrawTick
338 
339     Description:    Draw the model by using given scene parameters
340 
341     Arguments:      sc : pointer to the structure of scene control parameters
342 
343     Returns:        none
344  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)345 static void DrawTick( MySceneCtrlObj* sc )
346 {
347     GXRenderModeObj *rmp;
348     Mtx       mtg;
349     GXTexObj  to;
350     u16       shSize, scrWd, scrHt;
351     f32       adjf;
352 
353     // get current rendering mode structure
354     rmp   = DEMOGetRenderModeObj();
355     scrWd = rmp->fbWidth;
356     scrHt = rmp->efbHeight;
357 
358     GXInvalidateTexAll();
359     shSize = ShadowSizeTbl[sc->shadowTexSize];
360 
361     //-------------------------------------------
362     //    1st pass.
363     //    Make ID map viewed from the light
364     //-------------------------------------------
365 
366     // Set viewport/camera for making shadow texture
367     GXSetViewport(0, 0, shSize, shSize, 0.0F, 1.0F);
368     GXSetScissor(0, 0, (u32)shSize, (u32)shSize);
369     sc->light.cam.cfg = ( sc->projMode ) ?
370                         DefaultLightCamera1 : DefaultLightCamera0;
371     SetCamera(&sc->light.cam);
372 
373     // Set render mode which only draws ID number as a color
374     SetShaderModeFor1stPass();
375 
376     // Scale adjustment factor which can be used to enlarge
377     // drawing area of each object in the first pass
378     adjf = ( sc->adjMode ) ? 1.15F : 1.0F;
379 
380     // Draw models with ID
381     MTXIdentity(mtg);
382     DrawModels(sc->light.cam.view, mtg, adjf, &sc->anim);
383 
384 
385     //-------------------------------------------
386     //    Copy ID map into Texture
387     //-------------------------------------------
388 
389     // Turn off vertical de-flicker filter temporary
390     // (to avoid filtering while framebuffer-to-texture copy)
391     GXSetCopyFilter(GX_FALSE, NULL, GX_FALSE, NULL);
392 
393     // Copy shadow image into texture
394     GXSetTexCopySrc(0, 0, shSize, shSize);
395     GXSetTexCopyDst(shSize, shSize, SHADOW_TEX_CPFMT, GX_FALSE);
396     GXCopyTex(sc->shadowTexData, GX_TRUE);
397 
398     // Wait for finishing the copy task in the graphics pipeline
399     GXPixModeSync();
400 
401     // Restore vertical de-flicker filter mode
402     GXSetCopyFilter(rmp->aa, rmp->sample_pattern, GX_TRUE, rmp->vfilter);
403 
404 
405     //-------------------------------------------
406     //    2nd pass.
407     //    Make main image from the viewer
408     //-------------------------------------------
409 
410     // Set viewport/camera/light for the main image
411     GXSetViewport(0, 0, scrWd, scrHt, 0.0F, 1.0F);
412     GXSetScissor(0, 0, (u32)scrWd, (u32)scrHt);
413     SetCamera(&sc->cam);
414     SetLight(&sc->light, sc->cam.view);
415 
416     // Set shading target according to the current display mode
417     switch(sc->dispMode)
418     {
419       case 0 :
420         // Shows result scene with full-scene shadow
421         SetShaderModeFor2ndPass();
422         break;
423       case 1 :
424          // Shows ID number of each object
425         SetShaderModeFor1stPass();
426         break;
427       case 2 :
428       default:
429         // Shows projected object ID map (shadow map)
430         SetShaderModeForProj();
431         break;
432     }
433 
434     // Load object ID map (shadow map)
435     GXInitTexObj(
436         &to,
437         sc->shadowTexData,
438         shSize,
439         shSize,
440         SHADOW_TEX_FMT,
441         GX_CLAMP,
442         GX_CLAMP,
443         GX_FALSE );
444     GXInitTexObjLOD(&to, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
445     GXLoadTexObj(&to, GX_TEXMAP0);
446 
447     // Set up shadow projection
448     GetTexProjMtx(&sc->light.cam, mtg);
449 
450     // Draw models with IDs
451     DrawModels(sc->cam.view, mtg, 1.0F, &sc->anim);
452 }
453 
454 /*---------------------------------------------------------------------------*
455     Name:           AnimTick
456 
457     Description:    Changes scene parameters according to the pad status.
458 
459     Arguments:      sc  : pointer to the structure of scene control parameters
460 
461     Returns:        none
462  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)463 static void AnimTick( MySceneCtrlObj* sc )
464 {
465     u16 down = DEMOPadGetButtonDown(0);
466 
467     // Camera position
468     sc->cam.theta += ( DEMOPadGetStickX(0) / 24 );
469     sc->cam.theta = ( sc->cam.theta + 360 ) % 360;
470     sc->cam.phi   += ( DEMOPadGetStickY(0) / 24 );
471     Clamp(sc->cam.phi, 10, 60);
472 
473     // Light position
474     sc->light.cam.theta += ( DEMOPadGetSubStickX(0) / 24 );
475     sc->light.cam.theta = ( sc->light.cam.theta + 360 ) % 360;
476     sc->light.cam.phi += ( DEMOPadGetSubStickY(0) / 24 );
477     Clamp(sc->light.cam.phi, 15, 90);
478 
479     // Change display mode
480     if ( down & PAD_BUTTON_A )
481     {
482         sc->dispMode = (++sc->dispMode) % NUM_DISP_MODES;
483         OSReport("Mode = %s\n", DispModeMsg[sc->dispMode]);
484     }
485 
486     // Change shadow map size
487     if ( down & PAD_BUTTON_Y )
488     {
489         sc->shadowTexSize = (++sc->shadowTexSize) % NUM_SHADOW_SIZES;
490         OSReport(
491             "Shadow Size = %dx%d\n",
492             ShadowSizeTbl[sc->shadowTexSize],
493             ShadowSizeTbl[sc->shadowTexSize] );
494     }
495 
496     // Toggle shadow projection type
497     if ( down & PAD_BUTTON_B )
498     {
499         sc->projMode = ( sc->projMode == 0 ) ? 1U : 0U;
500         OSReport("Projection = %s\n", ProjModeMsg[sc->projMode]);
501     }
502 
503     // Object scale adjustment
504     if ( down & PAD_BUTTON_X )
505     {
506         sc->adjMode = ( sc->adjMode == 0 ) ? 1U : 0U;
507         OSReport("Scale adjustment = %s\n", AdjModeMsg[sc->adjMode]);
508     }
509 
510 
511     // Animating objects
512     sc->anim.ballX += sc->anim.ballVx;
513     if ( sc->anim.ballX > 450.0F )
514     {
515         sc->anim.ballVx = - BALL_VX_INI;
516     }
517     if ( sc->anim.ballX < -450.0F )
518     {
519         sc->anim.ballVx = BALL_VX_INI;
520     }
521 
522     sc->anim.ballZ  += sc->anim.ballVz;
523     sc->anim.ballVz -= 1.5F;    // gravity
524     if ( sc->anim.ballZ < 0.0F )
525     {
526         sc->anim.ballVz = BALL_VZ_INI;
527     }
528 
529     sc->anim.octaRot = ( sc->anim.octaRot + 5 ) % 360;
530 
531 }
532 
533 /*---------------------------------------------------------------------------*
534     Name:           DrawModels
535 
536     Description:    Draw all models with object ID and shadow
537                     projection texgen matrix
538 
539     Arguments:      view : view matrix
540                     tgv  : view & projection matrix for texgen
541                     adj  : scale adjustment factor
542                     anim : parameters for animating objects
543 
544     Returns:        none
545  *---------------------------------------------------------------------------*/
DrawModels(Mtx view,Mtx tgv,f32 adj,MyAnimCtrlObj * anim)546 static void DrawModels( Mtx view, Mtx tgv, f32 adj, MyAnimCtrlObj* anim )
547 {
548     u8     id = 0; // object ID for generating ID map
549     s32    i, j, x, y;
550     Mtx    mt, ms, mr, mm;
551 
552     // 8X values are used as ID numbers in order to visualize
553     // differences of IDs between an object and another.
554     // In general, you can use continuous integer numbers.
555 
556     // Cylinders
557     GXSetChanMatColor(GX_COLOR1A1, COL_MAT0);
558     GXSetTevColor(GX_TEVREG0, COL_SHADOW0); // TEVREG0 = shadow color
559 
560     MTXScale(ms, (f32)(40.0F*adj), (f32)(40.0F*adj), (f32)(300.0F*adj));
561     for ( i = -2 ; i < 3 ; ++i )
562     {
563         for ( j = -1 ; j < 2 ; j += 2 )
564         {
565             x = i - j;
566             y = i + j;
567             MTXTrans(mt, (f32)(x*150), (f32)(y*150), 200.0F);
568             MTXConcat(mt, ms, mm);
569             LoadGXMatrices(view, tgv, mm);
570 
571             id += 8;
572             SetModelID(id);
573             GXDrawCylinder(16);
574         }
575     }
576 
577     // Roofs
578     GXSetChanMatColor(GX_COLOR1A1, COL_MAT0);
579     GXSetTevColor(GX_TEVREG0, COL_SHADOW0); // TEVREG0 = shadow color
580 
581     MTXRotDeg(mr, 'z', 45);
582     MTXScale(ms, (f32)(80.0F*adj), (f32)(480.0F*adj), (f32)(60.0F*adj));
583     MTXConcat(mr, ms, ms);
584     for ( i = -2 ; i < 3 ; ++i )
585     {
586         MTXTrans(mt, (f32)(i*150), (f32)(i*150), 530.0F);
587         MTXConcat(mt, ms, mm);
588         LoadGXMatrices(view, tgv, mm);
589 
590         id += 8;
591         SetModelID(id);
592         GXDrawCube();
593     }
594 
595     // Bounding ball
596     GXSetChanMatColor(GX_COLOR1A1, COL_MAT1);
597     GXSetTevColor(GX_TEVREG0, COL_SHADOW1); // TEVREG0 = shadow color
598 
599     MTXScale(ms, (f32)(100.0F*adj), (f32)(100.0F*adj), (f32)(100.0F*adj));
600     MTXTrans(mt, anim->ballX, anim->ballX, anim->ballZ);
601     MTXConcat(mt, ms, mm);
602     LoadGXMatrices(view, tgv, mm);
603 
604     id += 8;
605     SetModelID(id);
606     GXDrawSphere1(1);
607 
608 
609     // Rotating octahedra
610     GXSetChanMatColor(GX_COLOR1A1, COL_MAT2);
611     GXSetTevColor(GX_TEVREG0, COL_SHADOW2); // TEVREG0 = shadow color
612 
613     MTXScale(ms, (f32)(150.0F*adj), (f32)(150.0F*adj), (f32)(150.0F*adj));
614     MTXRotDeg(mr, 'z', anim->octaRot);
615     MTXConcat(mr, ms, ms);
616     for ( i = -1 ; i <= 1 ; i += 2 )
617     {
618         MTXTrans(mt, (f32)(-i*400.0F), (f32)(i*400.0F), 50.0F);
619         MTXConcat(mt, ms, mm);
620         LoadGXMatrices(view, tgv, mm);
621 
622         id += 8;
623         SetModelID(id);
624         GXDrawOctahedron();
625     }
626 
627 
628     // Floor
629     GXSetChanMatColor(GX_COLOR1A1, COL_MAT3);
630     GXSetTevColor(GX_TEVREG0, COL_SHADOW3); // TEVREG0 = shadow color
631 
632     MTXScale(ms, (f32)(1000.0F*adj), (f32)(1000.0F*adj), (f32)(50.0F*adj));
633     MTXTrans(mt, 0.0F, 0.0F, -125.0F);
634     MTXConcat(mt, ms, mm);
635     LoadGXMatrices(view, tgv, mm);
636 
637     id += 8;
638     SetModelID(id);
639     GXDrawCube();
640 }
641 
642 /*---------------------------------------------------------------------------*
643     Name:           LoadGXMatrices
644 
645     Description:    Calculates each Pos/Nrm/Tex matrices and
646                     loads them into the hardware.
647 
648     Arguments:      view : view matrix
649                     tgv  : view & projection matrix for texgen
650                     mdm  : model transform matrix
651 
652     Returns:        none
653  *---------------------------------------------------------------------------*/
LoadGXMatrices(Mtx view,Mtx tgv,Mtx mdm)654 static void LoadGXMatrices( Mtx view, Mtx tgv, Mtx mdm )
655 {
656     Mtx mv, mvi;
657 
658     MTXConcat(view, mdm, mv);
659     GXLoadPosMtxImm(mv, GX_PNMTX0);
660     MTXInverse(mv, mvi);
661     MTXTranspose(mvi, mv);
662     GXLoadNrmMtxImm(mv, GX_PNMTX0);
663     MTXConcat(tgv, mdm, mv);
664     GXLoadTexMtxImm(mv, GX_TEXMTX0, GX_MTX3x4);
665 }
666 
667 /*---------------------------------------------------------------------------*
668     Name:           GetTexProjMtx
669 
670     Description:    sets texture coord generation matrix for shadow texture
671 
672     Arguments:      cam : pointer to the MyCameraObj structure
673                     mp  : a matrix the result should be set
674 
675     Returns:        none
676  *---------------------------------------------------------------------------*/
GetTexProjMtx(MyCameraObj * cam,Mtx mp)677 static void GetTexProjMtx( MyCameraObj* cam, Mtx mp )
678 {
679     Mtx proj;
680 
681     if ( cam->cfg.type == GX_PERSPECTIVE )
682     {
683         MTXLightFrustum(
684             proj,
685             - (cam->cfg.top), // t = -y in projected texture
686             cam->cfg.top,
687             cam->cfg.left,
688             - (cam->cfg.left),
689             cam->cfg.znear,
690             0.5F,
691             0.5F,
692             0.5F,
693             0.5F );
694     }
695     else // ( cam->cfg.type == GX_ORTHOGRAPHIC )
696     {
697         MTXLightOrtho(
698             proj,
699             - (cam->cfg.top), // t = -y in projected texture
700             cam->cfg.top,
701             cam->cfg.left,
702             - (cam->cfg.left),
703             0.5F,
704             0.5F,
705             0.5F,
706             0.5F );
707     }
708 
709     MTXConcat(proj, cam->view, mp);
710 }
711 
712 /*---------------------------------------------------------------------------*
713     Name:           SetModelID
714 
715     Description:    Sets ID number for next drawing object
716                     ID number is used for generating shadow map
717                     This program uses constant color output from color
718                     channel 0 for ID encoding. You can also use direct
719                     vertex color or TEV register value instead.
720 
721     Arguments:      id : ID number for the object (> 0)
722 
723     Returns:        none
724  *---------------------------------------------------------------------------*/
SetModelID(u8 id)725 static void SetModelID( u8 id )
726 {
727     GXColor  col;
728     col.r = col.g = col.b = id;
729 
730     GXSetChanMatColor(GX_COLOR0A0, col);
731 }
732 
733 /*---------------------------------------------------------------------------*
734     Name:           SetCamera
735 
736     Description:    set view matrix and load projection matrix into hardware
737 
738     Arguments:      cam : pointer to the MyCameraObj structure
739 
740     Returns:        none
741  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)742 static void SetCamera( MyCameraObj* cam )
743 {
744     f32  r_theta, r_phi;
745 
746     r_theta = (f32)cam->theta * PI / 180.0F;
747     r_phi   = (f32)cam->phi   * PI / 180.0F;
748 
749     cam->cfg.location.x =
750         cam->distance * cosf(r_theta) * cosf(r_phi);
751     cam->cfg.location.y =
752         cam->distance * sinf(r_theta) * cosf(r_phi);
753     cam->cfg.location.z =
754         cam->distance * sinf(r_phi);
755 
756     MTXLookAt(
757         cam->view,
758         &cam->cfg.location,
759         &cam->cfg.up,
760         &cam->cfg.target );
761 
762     if ( cam->cfg.type == GX_PERSPECTIVE )
763     {
764         MTXFrustum(
765             cam->proj,
766             cam->cfg.top,
767             - (cam->cfg.top),
768             cam->cfg.left,
769             - (cam->cfg.left),
770             cam->cfg.znear,
771             cam->cfg.zfar );
772     }
773     else // ( cam->cfg.type == GX_ORTHOGRAPHIC )
774     {
775         MTXOrtho(
776             cam->proj,
777             cam->cfg.top,
778             - (cam->cfg.top),
779             cam->cfg.left,
780             - (cam->cfg.left),
781             cam->cfg.znear,
782             cam->cfg.zfar );
783     }
784 
785     GXSetProjection(cam->proj, cam->cfg.type);
786 }
787 
788 /*---------------------------------------------------------------------------*
789     Name:           SetLight
790 
791     Description:    Set up light parameters
792 
793     Arguments:      light : pointer to a MyLightObj structure
794                     v     : view matrix
795 
796     Returns:        none
797  *---------------------------------------------------------------------------*/
SetLight(MyLightObj * light,Mtx v)798 void SetLight( MyLightObj* light, Mtx v )
799 {
800     Vec lpos = light->cam.cfg.location;
801 
802     // Multipled by view matrix
803     MTXMultVec(v, &lpos, &lpos);
804 
805     GXInitLightPos(&light->lobj, lpos.x, lpos.y, lpos.z);
806     GXInitLightColor(&light->lobj, COL_LIGHT);
807     GXLoadLightObjImm(&light->lobj, GX_LIGHT0);
808 }
809 
810 /*---------------------------------------------------------------------------*
811     Name:           SetShaderModeFor1stPass
812 
813     Description:    Set up shading mode (color channel, TEV, etc.)
814                     for 1st pass which generates object ID map for shadow.
815                     This pass only uses constant color set as material.
816 
817     Arguments:      none
818 
819     Returns:        none
820  *---------------------------------------------------------------------------*/
SetShaderModeFor1stPass(void)821 void SetShaderModeFor1stPass( void )
822 {
823     GXSetNumChans(1);
824     GXSetChanCtrl(
825         GX_COLOR0A0,
826         GX_DISABLE,    // enable channel
827         GX_SRC_REG,    // amb source
828         GX_SRC_REG,    // mat source
829         GX_LIGHT_NULL, // light mask
830         GX_DF_CLAMP,   // diffuse function
831         GX_AF_NONE );
832     // set up ambient color
833     GXSetChanAmbColor(GX_COLOR0A0, COL_BLACK);
834 
835     GXSetNumTevStages(1);
836     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
837     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
838 
839     GXSetNumTexGens(0);
840 }
841 
842 /*---------------------------------------------------------------------------*
843     Name:           SetShaderModeFor2ndPass
844 
845     Description:    Set up shading mode (coloe channel, TEV, etc.)
846                     for 2nd pass which draws actual scene from the
847                     viewer with full-scene shadow.
848 
849     Arguments:      none
850 
851     Returns:        none
852  *---------------------------------------------------------------------------*/
SetShaderModeFor2ndPass(void)853 void SetShaderModeFor2ndPass( void )
854 {
855     GXSetNumChans(2);
856 
857     // Still channel 0 is used to send ID
858     GXSetChanCtrl(
859         GX_COLOR0A0,
860         GX_DISABLE,    // enable channel
861         GX_SRC_REG,    // amb source
862         GX_SRC_REG,    // mat source
863         GX_LIGHT_NULL, // light mask
864         GX_DF_CLAMP,   // diffuse function
865         GX_AF_NONE );
866     GXSetChanAmbColor(GX_COLOR0A0, COL_BLACK);
867 
868     // channel 1 is used to lighting
869     GXSetChanCtrl(
870         GX_COLOR1A1,
871         GX_ENABLE,   // enable channel
872         GX_SRC_REG,  // amb source
873         GX_SRC_REG,  // mat source
874         GX_LIGHT0,   // light mask
875         GX_DF_CLAMP, // diffuse function
876         GX_AF_NONE );
877     GXSetChanAmbColor(GX_COLOR1A1, COL_AMBIENT);
878 
879     // texgen for shadow projection
880     GXSetNumTexGens(1);
881     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
882 
883     GXSetNumTevStages(2);
884 
885     // TEV Stage 0  ( Color0(R) == Texture0(R) ? 255 : 0 )
886     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
887     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_TEXC, GX_CC_RASC, GX_CC_ONE, GX_CC_ZERO);
888     GXSetTevColorOp(
889         GX_TEVSTAGE0,
890         GX_TEV_COMP_R8_EQ,  // R8 equal compare mode
891         GX_TB_ZERO,         // actually N/A
892         GX_CS_SCALE_1,      // actually N/A
893         GX_TRUE,
894         GX_TEVPREV );
895 
896     // TEV Stage 1  ( REGPREV == 0 ? Reg0 : Color1 )
897     // Register 0 is supporsed to hold shadow color
898     GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR1A1);
899     GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_C0, GX_CC_RASC, GX_CC_CPREV, GX_CC_ZERO);
900     GXSetTevColorOp(
901         GX_TEVSTAGE1,
902         GX_TEV_ADD,
903         GX_TB_ZERO,
904         GX_CS_SCALE_1,
905         GX_TRUE,
906         GX_TEVPREV );
907 }
908 
909 /*---------------------------------------------------------------------------*
910     Name:           SetShaderModeForProj
911 
912     Description:    Set up shading mode (color channel, TEV, etc.)
913                     for 2nd pass.
914                     This mode displays only projected shadow map.
915 
916     Arguments:      none
917 
918     Returns:        none
919  *---------------------------------------------------------------------------*/
SetShaderModeForProj(void)920 void SetShaderModeForProj( void )
921 {
922     GXSetNumChans(0);
923 
924     GXSetNumTevStages(1);
925     GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
926     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
927 
928     GXSetNumTexGens(1);
929     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
930 }
931 
932 /*---------------------------------------------------------------------------*
933     Name:           PrintIntro
934 
935     Description:    Prints the directions on how to use this demo.
936 
937     Arguments:      none
938 
939     Returns:        none
940  *---------------------------------------------------------------------------*/
PrintIntro(void)941 static void PrintIntro( void )
942 {
943     OSReport("\n\n");
944     OSReport("******************************************************\n");
945     OSReport("tg-shadow2: full-scene shadow by object ID map\n");
946     OSReport("******************************************************\n");
947     OSReport("to quit hit the start button\n");
948     OSReport("\n");
949     OSReport("Main stick : Move the camera\n");
950     OSReport("Sub stick  : Move the light\n");
951     OSReport("A button   : Change display mode\n");
952     OSReport("B button   : Change projection type\n");
953     OSReport("X button   : Scale adjustment ON/OFF\n");
954     OSReport("Y button   : Change shadow map size\n");
955     OSReport("******************************************************\n");
956     OSReport("\n\n");
957 }
958 
959 /*============================================================================*/
960