1 /*---------------------------------------------------------------------------*
2   Project:  Dolphin/Revolution gx demo
3   File:     tg-shadow3.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-shadow3
15        Full-scene shadow method by texture copy from Z buffer
16  *---------------------------------------------------------------------------*
17 
18    Overview of this method:
19 
20        (1st. pass) Render the entire scene from the light's point
21        of view. Since only geometry information is necessary,
22        color update is turned off. Only Z buffer will be updated.
23        And front-face culling helps creating shadow map of "second"
24        visible surfaces which can avoid the "first" lit surfaces
25        to become shadow.
26 
27        Copy the result Z buffer into a texture (shadow map).
28        Z buffer is cleared at the same time.
29 
30        (2nd. pass) Render the entire scene viewed from the camera.
31        Then load the shadow map and apply texture coord projection
32        from the light. And also get the distance from the light
33        which can be obtained by looking up a ramp texture with
34        appropriate texture coordinate generation matrix. Compare
35        these two values (shadow map and distance) and detect whether
36        a point should become shadow. If Z data from shadow map is
37        less than actual distance, it means a ray from the light is
38        obstructed by an another polygon and the point becomes shadow.
39        The comparison is done by some TEV stages where Z values are
40        considered as color data.
41 
42        This demo shows both 8bit/16bit Z precision comparison scheme.
43 
44  *---------------------------------------------------------------------------*/
45 
46 /*---------------------------------------------------------------------------*
47    Header files
48  *---------------------------------------------------------------------------*/
49 #include <demo.h>
50 #include <math.h>
51 
52 /*---------------------------------------------------------------------------*
53    Macro definitions
54  *---------------------------------------------------------------------------*/
55 #define PI               3.14159265F
56 #define MAX_Z            0x00ffffff // max value of Z buffer
57 
58 #define NUM_SHADOW_SIZES 4
59 #define NUM_DISP_MODES   6
60 
61 // For drawing objects
62 #define NUM_GRIDS        8
63 #define SP_NUMR          16
64 
65 // For shadowing
66 #define SHADOW_TEX_MAX   400
67 
68 #define Clamp(val,min,max) \
69     ((val) = (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val)))
70 
71 /*---------------------------------------------------------------------------*
72   Structure definitions
73  *---------------------------------------------------------------------------*/
74 // for camera
75 typedef struct
76 {
77     Vec               location;
78     Vec               up;
79     Vec               target;
80     f32               left;
81     f32               top;
82     f32               znear;
83     f32               zfar;
84     GXProjectionType  type;
85 } CameraConfig;
86 
87 typedef struct
88 {
89     CameraConfig      cfg;
90     Mtx               view;
91     Mtx44             proj;
92     s32               theta;
93     s32               phi;
94     f32               distance;
95 } MyCameraObj;
96 
97 // for light
98 typedef struct
99 {
100     GXLightObj    lobj;
101     MyCameraObj   cam;  // for projection
102 } MyLightObj;
103 
104 // for packing various transform matrices
105 typedef struct
106 {
107     Mtx    view;     // Viewing transformation
108     Mtx    texProj;  // Texgen for projected shadow map
109     Mtx    depth;    // Texgen for depth value lookup
110 } MyTransMtxObj;
111 
112 // for entire scene control
113 typedef struct
114 {
115     MyCameraObj   cam;
116     MyLightObj    light;
117     u32           dispMode;
118     u32           projMode;
119     s32           modelRot;
120     u8*           shadowTexData;
121     u32           shadowTexSize;
122     u16           screen_wd;
123     u16           screen_ht;
124 } MySceneCtrlObj;
125 
126 /*---------------------------------------------------------------------------*
127    Forward references
128  *---------------------------------------------------------------------------*/
129 void        main            ( void );
130 static void DrawInit        ( MySceneCtrlObj* sc );
131 static void DrawTick        ( MySceneCtrlObj* sc );
132 static void AnimTick        ( MySceneCtrlObj* sc );
133 static void DrawModels      ( MyTransMtxObj* tmo, s32 rot );
134 static void DrawFloor       ( void );
135 static void DrawSpiral      ( u32 roll );
136 static void LoadGXMatrices  ( MyTransMtxObj* tmo, Mtx mm );
137 static void GetTexProjMtx   ( MyTransMtxObj* tmo, MyCameraObj* cam, u8 bitMode );
138 static void SetCamera       ( MyCameraObj* cam );
139 static void SetLight        ( MyLightObj* light, Mtx v );
140 
141 static void SetShaderModeFor1stPass     ( void );
142 static void SetShaderModeFor2ndPass8    ( void );
143 static void SetShaderModeFor2ndPass16   ( void );
144 static void SetShaderModeForProj8       ( void );
145 static void SetShaderModeForProj16      ( void );
146 static void SetShaderModeForDepth8      ( void );
147 static void SetShaderModeForDepth16     ( void );
148 
149 static void CreateRampTex8  ( GXTexObj* to );
150 static void CreateRampTex16 ( GXTexObj* to );
151 static void PrintIntro      ( void );
152 
153 /*---------------------------------------------------------------------------*
154    Lighting parameters
155  *---------------------------------------------------------------------------*/
156 #define COL_BLACK    MyColors[0]
157 #define COL_GREEN    MyColors[1]
158 #define COL_RED      MyColors[2]
159 #define COL_YELLOW   MyColors[3]
160 #define COL_AMBIENT  MyColors[4]
161 #define COL_LIGHT    MyColors[5]
162 #define COL_MAT0     MyColors[6]
163 #define COL_SHADOW0  MyColors[7]
164 #define COL_MAT1     MyColors[8]
165 #define COL_SHADOW1  MyColors[9]
166 #define COL_MAT2     MyColors[10]
167 #define COL_SHADOW2  MyColors[11]
168 
169 static GXColor MyColors[] ATTRIBUTE_ALIGN(32) =
170 {
171     {0x00, 0x00, 0x00, 0xff},  // black
172     {0x00, 0xff, 0x00, 0xff},  // green
173     {0xff, 0x00, 0x00, 0xff},  // red
174     {0xff, 0xff, 0x00, 0xff},  // yellow
175     {0x40, 0x40, 0x40, 0xff},  // ambient
176     {0xb0, 0xb0, 0xb0, 0xff},  // light color
177     {0xf0, 0xf0, 0xf0, 0xff},  // material color 0
178     {0x3C, 0x3C, 0x3C, 0xff},  // shadow color 0
179     {0x80, 0xff, 0x80, 0xff},  // material color 1
180     {0x20, 0x40, 0x20, 0xff},  // shadow color 1
181     {0xA0, 0xc0, 0xff, 0xff},  // material color 2
182     {0x28, 0x30, 0x40, 0xff},  // shadow color 2
183 };
184 
185 // fixed normal vector
186 static f32 FixedNormal[] ATTRIBUTE_ALIGN(32) =
187 {
188     1.0F,  0.0F,  0.0F,  // +X
189    -1.0F,  0.0F,  0.0F,  // -X
190     0.0F,  1.0F,  0.0F,  // +Y
191     0.0F, -1.0F,  0.0F,  // -Y
192     0.0F,  0.0F,  1.0F,  // +Z
193     0.0F,  0.0F, -1.0F   // -Z
194 };
195 
196 /*---------------------------------------------------------------------------*
197    Floor elevation map data
198  *---------------------------------------------------------------------------*/
199 static s8 FloorElvTbl[NUM_GRIDS][NUM_GRIDS] =
200 {
201     { 6, 4, 2, 4, 3, 5, 1, 1 },
202     { 4, 1, 1, 3, 2, 2, 1, 1 },
203     { 1, 1, 5, 1, 1, 5, 3, 5 },
204     { 1, 1, 1, 1, 1, 4, 2, 3 },
205     { 5, 4, 1, 1, 1, 1, 1, 1 },
206     { 7, 5, 2, 1, 1, 5, 1, 1 },
207     { 1, 1, 5, 7, 3, 1, 1, 3 },
208     { 1, 1, 3, 5, 1, 1, 6, 2 }
209 };
210 
211 /*---------------------------------------------------------------------------*
212    Shadow texture size table
213  *---------------------------------------------------------------------------*/
214 static u16 ShadowSizeTbl[NUM_SHADOW_SIZES] =
215 {
216     400, 256, 128, 64
217 };
218 
219 /*---------------------------------------------------------------------------*
220    Strings for messages
221  *---------------------------------------------------------------------------*/
222 static char* DispModeMsg[NUM_DISP_MODES] =
223 {
224     "result scene (8bit depth)",
225     "actual depth from the light (8bit depth)",
226     "projected shadow depth map (8bit depth)",
227     "result scene (16bit depth)",
228     "actual depth from the light (16bit depth)",
229     "projected shadow depth map (16bit depth)"
230 };
231 
232 static char* ProjModeMsg[] =
233 {
234     "Perspective",
235     "Orthographic"
236 };
237 
238 /*---------------------------------------------------------------------------*
239    Camera configuration
240  *---------------------------------------------------------------------------*/
241 static CameraConfig DefaultCamera =
242 {
243     { 1.0F, 1.0F, 1.0F }, // location (Not used)
244     { 0.0F, 0.0F, 1.0F }, // up
245     { 0.0F, 0.0F, 0.0F }, // target
246     -160.0F,  // left
247     120.0F,   // top
248     300.0F,   // near
249     5000.0F,  // far
250     GX_PERSPECTIVE // type
251 };
252 
253 // Perspective projection for local light effect
254 static CameraConfig DefaultLightCamera0 =
255 {
256     { 1.0F, 1.0F, 1.0F }, // location (Not used)
257     { 0.0F, 0.0F, 1.0F }, // up
258     { 0.0F, 0.0F, 0.0F }, // target
259     -640.0F,  // left
260      640.0F,  // top
261     2000.0F,  // near
262     4000.0F,  // far
263     GX_PERSPECTIVE // type
264 };
265 
266 // Orthographic projection for infinite light effect
267 static CameraConfig DefaultLightCamera1 =
268 {
269     { 1.0F, 1.0F, 1.0F }, // location (Not used)
270     { 0.0F, 0.0F, 1.0F }, // up
271     { 0.0F, 0.0F, 0.0F }, // target
272     -960.0F, // left
273      960.0F, // top
274     2000.0F, // near
275     4000.0F, // far
276     GX_ORTHOGRAPHIC // type
277 };
278 
279 /*---------------------------------------------------------------------------*
280    Global Variables
281  *---------------------------------------------------------------------------*/
282 static MySceneCtrlObj  SceneCtrl; // scene control parameters
283 static GXTexObj        RampTex8;  // 8 bit ramp texture
284 static GXTexObj        RampTex16; // 16 bit ramp texture
285 
286 /*---------------------------------------------------------------------------*
287    Application main loop
288  *---------------------------------------------------------------------------*/
main(void)289 void main ( void )
290 {
291     DEMOInit(NULL);       // Init the OS, game pad, graphics and video.
292 
293     DrawInit(&SceneCtrl); // Initialize vertex formats and scene parameters etc.
294 
295     PrintIntro();  // Print demo directions
296 
297     while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
298     {
299         DEMOBeforeRender();
300         DrawTick(&SceneCtrl);    // Draw the model.
301         DEMODoneRender();
302         DEMOPadRead();
303         AnimTick(&SceneCtrl);    // Update animation.
304     }
305 
306     OSHalt("End of demo");
307 }
308 
309 /*---------------------------------------------------------------------------*
310    Functions
311  *---------------------------------------------------------------------------*/
312 /*---------------------------------------------------------------------------*
313     Name:           DrawInit
314 
315     Description:    Initializes the vertex attribute format, texture and
316                     default scene parameters.
317 
318     Arguments:      sc : pointer to the structure of scene control parameters
319 
320     Returns:        none
321  *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)322 static void DrawInit( MySceneCtrlObj* sc )
323 {
324     GXRenderModeObj *rmp;
325     u32    size;
326 
327     // get framebuffer size of current rendering mode
328     rmp = DEMOGetRenderModeObj();
329     sc->screen_wd = rmp->fbWidth;
330     sc->screen_ht = rmp->efbHeight;
331 
332     // set up a vertex attribute
333     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S8, 0);
334     GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
335     GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
336     GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
337 
338     // Set pixel format and background color
339     GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
340     GXSetCopyClear(COL_BLACK, MAX_Z);
341 
342     // Perform dummy copy to clear EFB by specified color
343     GXCopyDisp(DEMOGetCurrentBuffer(), GX_TRUE);
344 
345     // Create ramp textures
346     CreateRampTex8(&RampTex8);
347     CreateRampTex16(&RampTex16);
348 
349 
350     // Default scene parameter settings
351 
352     // camera
353     sc->cam.cfg      = DefaultCamera;
354     sc->cam.theta    = 45;
355     sc->cam.phi      = 25;
356     sc->cam.distance = 2000.0F;
357 
358     // Light camera
359     sc->projMode           = 0;
360     sc->light.cam.theta    = 0;
361     sc->light.cam.phi      = 60;
362     sc->light.cam.distance = 3000.0F;
363 
364     // display mode and shadow map control mode
365     sc->dispMode      = 0;
366     sc->shadowTexSize = 0;
367 
368     // animating objects
369     sc->modelRot = 0;
370 
371     // Memory area for dynamic shadow map
372     size = GXGetTexBufferSize(
373                SHADOW_TEX_MAX,
374                SHADOW_TEX_MAX,
375                GX_TF_RGBA8,
376                GX_FALSE,
377                0 );
378     sc->shadowTexData = MEMAllocFromAllocator(&DemoAllocator1, size);
379 
380 }
381 
382 /*---------------------------------------------------------------------------*
383     Name:           DrawTick
384 
385     Description:    Draw the scene by using given scene parameters
386 
387     Arguments:      sc : pointer to the structure of scene control parameters
388 
389     Returns:        none
390  *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)391 static void DrawTick( MySceneCtrlObj* sc )
392 {
393     MyTransMtxObj   tmo;
394     GXTexObj        to;
395     GXTexFmt        shFmt, shCpFmt;
396     u16             shSize;
397 
398     // Invalidate texture cache
399     GXInvalidateTexAll();
400 
401     // Shadow map texture setting
402     shSize = ShadowSizeTbl[sc->shadowTexSize];
403 
404     if ( sc->dispMode <= 2 )
405     {
406         // 8bit mode
407         shCpFmt = GX_TF_Z8;
408         shFmt   = GX_TF_I8;
409     }
410     else
411     {
412         // 16bit mode
413         shCpFmt = GX_TF_Z16;
414         shFmt   = GX_TF_IA8;
415     }
416 
417     //-------------------------------------------
418     //  1st. pass
419     //  Make an image viewed from the light
420     //-------------------------------------------
421 
422     // Color update is disabled. Only Z will be updated.
423     GXSetColorUpdate(GX_DISABLE);
424 
425     // To draw "second" surfaces from the light
426     GXSetCullMode(GX_CULL_FRONT);
427 
428     // Set viewport for making shadow texture
429     GXSetViewport(0, 0, shSize, shSize, 0.0F, 1.0F);
430     GXSetScissor(0, 0, (u32)shSize, (u32)shSize);
431 
432     // Set camera configuration
433     sc->light.cam.cfg = ( sc->projMode ) ?
434                         DefaultLightCamera1 : DefaultLightCamera0;
435     SetCamera(&sc->light.cam);
436 
437     // Set render mode to use only constant color
438     // because we need only depth buffer
439     SetShaderModeFor1stPass();
440 
441     // Draw models
442     MTXCopy(sc->light.cam.view, tmo.view);
443     DrawModels(&tmo, sc->modelRot);
444 
445 
446     //-------------------------------------------
447     //  Copy shadow depth map into Texture
448     //-------------------------------------------
449 
450     // Copy shadow image into texture
451     GXSetTexCopySrc(0, 0, shSize, shSize);
452     GXSetTexCopyDst(shSize, shSize, shCpFmt, GX_FALSE);
453     GXCopyTex(sc->shadowTexData, GX_TRUE);
454 
455     // Wait for finishing the copy task in the graphics pipeline
456     GXPixModeSync();
457 
458     //-------------------------------------------
459     //  2nd. pass
460     //  Make an image viewed from the camera
461     //-------------------------------------------
462 
463     // Enable color update
464     GXSetColorUpdate(GX_ENABLE);
465 
466     // Restore culling mode to normal
467     GXSetCullMode(GX_CULL_BACK);
468 
469     // Set viewport/camera/light for the main image
470     GXSetViewport(0, 0, sc->screen_wd, sc->screen_ht, 0.0F, 1.0F);
471     GXSetScissor(0, 0, (u32)sc->screen_wd, (u32)sc->screen_ht);
472     SetCamera(&sc->cam);
473     SetLight(&sc->light, sc->cam.view);
474 
475     // Set up shadow map texture
476     GXInitTexObj(
477         &to,
478         sc->shadowTexData,
479         shSize,
480         shSize,
481         shFmt,
482         GX_CLAMP,
483         GX_CLAMP,
484         GX_FALSE );
485     GXInitTexObjLOD(&to, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
486 
487 
488     // Set shading mode according to the current display mode
489     switch(sc->dispMode)
490     {
491       case 0 :
492         // Shows actual result scene (8bit comparison)
493         SetShaderModeFor2ndPass8();
494         GetTexProjMtx(&tmo, &sc->light.cam, 0);
495         GXLoadTexObj(&RampTex8, GX_TEXMAP0);
496         GXLoadTexObj(&to, GX_TEXMAP1);
497         break;
498       case 1 :
499         // Shows depth from the light (8bit)
500         SetShaderModeForDepth8();
501         GetTexProjMtx(&tmo, &sc->light.cam, 0);
502         GXLoadTexObj(&RampTex8, GX_TEXMAP0);
503         break;
504       case 2 :
505         // Shows projected shadow depth map (8bit)
506         SetShaderModeForProj8();
507         GetTexProjMtx(&tmo, &sc->light.cam, 0);
508         GXLoadTexObj(&to, GX_TEXMAP0);
509         break;
510       case 3 :
511         // Shows actual result scene (16bit comparison)
512         SetShaderModeFor2ndPass16();
513         GetTexProjMtx(&tmo, &sc->light.cam, 1);
514         GXLoadTexObj(&RampTex16, GX_TEXMAP0);
515         GXLoadTexObj(&to, GX_TEXMAP1);
516         break;
517       case 4 :
518         // Shows depth from the light (16bit)
519         SetShaderModeForDepth16();
520         GetTexProjMtx(&tmo, &sc->light.cam, 1);
521         GXLoadTexObj(&RampTex16, GX_TEXMAP0);
522         break;
523       case 5 :
524       default:
525         // Shows projected shadow depth map (16bit)
526         SetShaderModeForProj16();
527         GetTexProjMtx(&tmo, &sc->light.cam, 1);
528         GXLoadTexObj(&to, GX_TEXMAP0);
529         break;
530     }
531 
532     // Draw models
533     MTXCopy(sc->cam.view, tmo.view);
534     DrawModels(&tmo, sc->modelRot);
535 }
536 
537 /*---------------------------------------------------------------------------*
538     Name:           AnimTick
539 
540     Description:    Changes scene parameters according to the pad status.
541 
542     Arguments:      sc : pointer to the structure of scene control parameters
543 
544     Returns:        none
545  *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)546 static void AnimTick( MySceneCtrlObj* sc )
547 {
548     u16 down = DEMOPadGetButtonDown(0);
549 
550     // Camera position
551     sc->cam.theta += ( DEMOPadGetStickX(0) / 24 );
552     sc->cam.theta = ( sc->cam.theta + 360 ) % 360;
553     sc->cam.phi   += ( DEMOPadGetStickY(0) / 24 );
554     Clamp(sc->cam.phi, 10, 60);
555 
556     // Light position
557     sc->light.cam.theta += ( DEMOPadGetSubStickX(0) / 24 );
558     sc->light.cam.theta = ( sc->light.cam.theta + 360 ) % 360;
559     sc->light.cam.phi += ( DEMOPadGetSubStickY(0) / 24 );
560     Clamp(sc->light.cam.phi, 15, 90);
561 
562     // Change display mode
563     if ( down & PAD_BUTTON_A )
564     {
565         sc->dispMode = (++sc->dispMode) % NUM_DISP_MODES;
566         OSReport("Mode = %s\n", DispModeMsg[sc->dispMode]);
567     }
568 
569     // Change shadow map size
570     if ( down & PAD_BUTTON_Y )
571     {
572         sc->shadowTexSize = (++sc->shadowTexSize) % NUM_SHADOW_SIZES;
573         OSReport(
574             "Shadow Size = %dx%d\n",
575             ShadowSizeTbl[sc->shadowTexSize],
576             ShadowSizeTbl[sc->shadowTexSize] );
577     }
578 
579     // Toggle shadow projection type
580     if ( down & PAD_BUTTON_B )
581     {
582         sc->projMode = ( sc->projMode == 0 ) ? 1U : 0U;
583         OSReport("Projection = %s\n", ProjModeMsg[sc->projMode]);
584     }
585 
586     sc->modelRot = ( sc->modelRot + 5 ) % 360;
587 
588 }
589 
590 /*---------------------------------------------------------------------------*
591     Name:           DrawModels
592 
593     Description:    Draw all models included in the scene
594 
595     Arguments:      tmo : a transform matrix set which includes view
596                           matrix and texgen matrix
597                     rot : rotation parameter for animating object
598 
599     Returns:        none
600  *---------------------------------------------------------------------------*/
DrawModels(MyTransMtxObj * tmo,s32 rot)601 static void DrawModels( MyTransMtxObj* tmo, s32 rot )
602 {
603     s32    i, j, x, y;
604     Mtx    mt, ms, mr, mm;
605 
606     // Columns
607     GXSetChanMatColor(GX_COLOR0A0, COL_MAT0);
608     GXSetTevColor(GX_TEVREG0, COL_SHADOW0); // TEVREG0 = shadow color
609 
610     MTXScale(ms, 40.0F, 40.0F, 300.0F);
611     for ( i = -2 ; i < 3 ; ++i )
612     {
613         for ( j = -1 ; j < 2 ; j += 2 )
614         {
615             x = i - j;
616             y = i + j;
617             MTXTrans(mt, (f32)(x*150), (f32)(y*150), 200.0F);
618             MTXConcat(mt, ms, mm);
619             LoadGXMatrices(tmo, mm);
620 
621             GXDrawCylinder(16);
622         }
623     }
624 
625     // Roofs
626     GXSetChanMatColor(GX_COLOR0A0, COL_MAT0);
627     GXSetTevColor(GX_TEVREG0, COL_SHADOW0); // TEVREG0 = shadow color
628 
629     MTXRotDeg(mr, 'z', 45);
630     MTXScale(ms, 80.0F, 480.0F, 60.0F);
631     MTXConcat(mr, ms, ms);
632     for ( i = -2 ; i < 3 ; ++i )
633     {
634         MTXTrans(mt, (f32)(i*150), (f32)(i*150), 530.0F);
635         MTXConcat(mt, ms, mm);
636         LoadGXMatrices(tmo, mm);
637 
638         GXDrawCube();
639     }
640 
641     // Rotating spiral objects
642     GXSetChanMatColor(GX_COLOR0A0, COL_MAT1);
643     GXSetTevColor(GX_TEVREG0, COL_SHADOW1); // TEVREG0 = shadow color
644 
645     MTXScale(ms, 125.0F, 125.0F, 20.0F);
646     MTXRotDeg(mr, 'z', rot);
647     MTXConcat(mr, ms, ms);
648     for ( i = -1 ; i <= 1 ; i += 2 )
649     {
650         MTXTrans(mt, (f32)(-i*450.0F), (f32)(i*450.0F), -100.0F);
651         MTXConcat(mt, ms, mm);
652         LoadGXMatrices(tmo, mm);
653 
654         DrawSpiral(5);
655     }
656 
657     // Floor
658     GXSetChanMatColor(GX_COLOR0A0, COL_MAT2);
659     GXSetTevColor(GX_TEVREG0, COL_SHADOW2); // TEVREG0 = shadow color
660 
661     MTXTrans(mt, - (f32)NUM_GRIDS / 2, -(f32)NUM_GRIDS / 2, -5);
662     MTXScale(ms, 150.0F, 150.0F, 25.0F);
663     MTXConcat(ms, mt, mm);
664     LoadGXMatrices(tmo, mm);
665 
666     DrawFloor();
667 }
668 
669 /*---------------------------------------------------------------------------*
670     Name:           DrawFloor
671 
672     Description:    Draws the floor which contains some steps
673 
674     Arguments:      none
675 
676     Returns:        none
677  *---------------------------------------------------------------------------*/
DrawFloor(void)678 static void DrawFloor( void )
679 {
680     s8  x, y, z0, z1;
681     u8  n;
682 
683     // set up vertex descriptors
684     GXClearVtxDesc();
685     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
686     GXSetVtxDesc(GX_VA_NRM, GX_INDEX8);
687 
688     // normal array
689     GXSetArray(GX_VA_NRM, FixedNormal, 3 * sizeof(f32));
690 
691     // Z side
692     for ( y = 0 ; y < NUM_GRIDS ; ++y )
693     {
694         GXBegin(GX_QUADS, GX_VTXFMT0, NUM_GRIDS * 4);
695             for ( x = 0 ; x < NUM_GRIDS ; ++x )
696             {
697                 z0 = FloorElvTbl[y][x];
698 
699                 GXPosition3s8(x, y, z0);
700                 GXNormal1x8(4);
701                 GXPosition3s8(x, (s8)(y+1), z0);
702                 GXNormal1x8(4);
703                 GXPosition3s8((s8)(x+1), (s8)(y+1), z0);
704                 GXNormal1x8(4);
705                 GXPosition3s8((s8)(x+1), y, z0);
706                 GXNormal1x8(4);
707             }
708         GXEnd();
709     }
710 
711     // X side
712     for ( y = 0 ; y < NUM_GRIDS ; ++y )
713     {
714         // This may generate small blank between two tiles
715         GXBegin(GX_QUADS, GX_VTXFMT0, (NUM_GRIDS + 1) * 4);
716             for ( x = 0 ; x <= NUM_GRIDS ; ++x )
717             {
718                 z0 = (s8)(( x == 0 ) ? 0 : FloorElvTbl[y][x-1]);
719                 z1 = (s8)(( x == NUM_GRIDS ) ? 0 : FloorElvTbl[y][x]);
720                 n  = (u8)(( z0 > z1 ) ? 0 : 1);
721 
722                 GXPosition3s8(x, y, z0);
723                 GXNormal1x8(n);
724                 GXPosition3s8(x, (s8)(y+1), z0);
725                 GXNormal1x8(n);
726                 GXPosition3s8(x, (s8)(y+1), z1);
727                 GXNormal1x8(n);
728                 GXPosition3s8(x, y, z1);
729                 GXNormal1x8(n);
730             }
731         GXEnd();
732     }
733 
734     // Y side
735     for ( x = 0 ; x < NUM_GRIDS ; ++x )
736     {
737         // This may generate small blank between two tiles
738         GXBegin(GX_QUADS, GX_VTXFMT0, (NUM_GRIDS + 1) * 4);
739             for ( y = 0 ; y <= NUM_GRIDS ; ++y )
740             {
741                 z0 = (s8)(( y == 0 ) ? 0 : FloorElvTbl[y-1][x]);
742                 z1 = (s8)(( y == NUM_GRIDS ) ? 0 : FloorElvTbl[y][x]);
743                 n  = (u8)(( z0 > z1 ) ? 2 : 3);
744 
745                 GXPosition3s8(x, y, z0);
746                 GXNormal1x8(n);
747                 GXPosition3s8(x, y, z1);
748                 GXNormal1x8(n);
749                 GXPosition3s8((s8)(x+1), y, z1);
750                 GXNormal1x8(n);
751                 GXPosition3s8((s8)(x+1), y, z0);
752                 GXNormal1x8(n);
753             }
754         GXEnd();
755     }
756 }
757 
758 /*---------------------------------------------------------------------------*
759     Name:           DrawSpiral
760 
761     Description:    Draws a spiral object
762 
763     Arguments:      roll : number of rolls
764 
765     Returns:        none
766  *---------------------------------------------------------------------------*/
DrawSpiral(u32 roll)767 static void DrawSpiral( u32 roll )
768 {
769     s32  i;
770     u16  nv;
771     f32  dx[SP_NUMR], dy[SP_NUMR];
772     f32  px, py, pz, dr;
773 
774     // set up sin/cos table
775     for ( i = 0 ; i < SP_NUMR ; ++i )
776     {
777         dr = 2.0F * PI * i / SP_NUMR;
778         dx[i] = cosf(dr);
779         dy[i] = sinf(dr);
780     }
781     nv = (u16)((roll*SP_NUMR+1) * 2);
782 
783     // set up vertex descriptors
784     GXClearVtxDesc();
785     GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
786     GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
787 
788     // Upper side
789     GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, nv);
790         for ( i = 0 ; i <= SP_NUMR*roll ; ++i )
791         {
792             px = dx[i % SP_NUMR];
793             py = dy[i % SP_NUMR];
794             pz = 1.0F + 2.0F * PI * i / SP_NUMR;
795 
796             GXPosition3f32(px, py, pz);
797             GXNormal3f32(-px, -py, 1.0F);
798             GXPosition3f32(px*0.5F, py*0.5F, pz);
799             GXNormal3f32(-px, -py, 0.5F);
800         }
801     GXEnd();
802 
803     // Lower side
804     GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, nv);
805         for ( i = 0 ; i <= SP_NUMR*roll ; ++i )
806         {
807             px = dx[i % SP_NUMR];
808             py = dy[i % SP_NUMR];
809             pz = 2.0F * PI * i / SP_NUMR;
810 
811             GXPosition3f32(px*0.5F, py*0.5F, pz);
812             GXNormal3f32(-px, -py, -0.5F);
813             GXPosition3f32(px, py, pz);
814             GXNormal3f32(-px, -py, -1.0F);
815         }
816     GXEnd();
817 
818     // Outside
819     GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, nv);
820         for ( i = 0 ; i <= SP_NUMR*roll ; ++i )
821         {
822             px = dx[i % SP_NUMR];
823             py = dy[i % SP_NUMR];
824             pz = 2.0F * PI * i / SP_NUMR;
825 
826             GXPosition3f32(px, py, pz);
827             GXNormal3f32(px, py, 0.0F);
828             GXPosition3f32(px, py, pz+1.0F);
829             GXNormal3f32(px, py, 0.0F);
830         }
831     GXEnd();
832 
833     // Inside
834     GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT1, nv);
835         for ( i = 0 ; i <= SP_NUMR*roll ; ++i )
836         {
837             px = dx[i % SP_NUMR];
838             py = dy[i % SP_NUMR];
839             pz = 2.0F * PI * i / SP_NUMR;
840 
841             GXPosition3f32(px*0.5F, py*0.5F, pz+1.0F);
842             GXNormal3f32(-px, -py, 0.0F);
843             GXPosition3f32(px*0.5F, py*0.5F, pz);
844             GXNormal3f32(-px, -py, 0.0F);
845         }
846     GXEnd();
847 
848     // Both ends
849     GXBegin(GX_QUADS, GX_VTXFMT1, 8);
850 
851         px = dx[0];
852         py = dy[0];
853         pz = 2.0F * PI * roll;
854 
855         GXPosition3f32(px*0.5F, py*0.5F, 0.0F);
856         GXNormal3f32(py, -px, 0.0F);
857         GXPosition3f32(px*0.5F, py*0.5F, 1.0F);
858         GXNormal3f32(py, -px, 0.0F);
859         GXPosition3f32(px, py, 1.0F);
860         GXNormal3f32(py, -px, 0.0F);
861         GXPosition3f32(px, py, 0.0F);
862         GXNormal3f32(py, -px, 0.0F);
863 
864         GXPosition3f32(px*0.5F, py*0.5F, pz+1.0F);
865         GXNormal3f32(py, px, 0.0F);
866         GXPosition3f32(px*0.5F, py*0.5F, pz);
867         GXNormal3f32(py, px, 0.0F);
868         GXPosition3f32(px, py, pz);
869         GXNormal3f32(py, px, 0.0F);
870         GXPosition3f32(px, py, pz+1.0F);
871         GXNormal3f32(py, px, 0.0F);
872 
873     GXEnd();
874 }
875 
876 /*---------------------------------------------------------------------------*
877     Name:           LoadGXMatrices
878 
879     Description:    Calculates each Pos/Nrm/Tex matrix and
880                     loads them into the hardware.
881 
882     Arguments:      tmo : MyTransMtxObj structure which includes
883                            view and texgen matrices
884                     mm  : model transformation matrix
885 
886     Returns:        none
887  *---------------------------------------------------------------------------*/
LoadGXMatrices(MyTransMtxObj * tmo,Mtx mm)888 static void LoadGXMatrices( MyTransMtxObj* tmo, Mtx mm )
889 {
890     Mtx mv, mvi;
891 
892     // Position and Normal
893     MTXConcat(tmo->view, mm, mv);
894     GXLoadPosMtxImm(mv, GX_PNMTX0);
895     MTXInverse(mv, mvi);
896     MTXTranspose(mvi, mv);
897     GXLoadNrmMtxImm(mv, GX_PNMTX0);
898     // Tex coord generation for depth value lookup
899     MTXConcat(tmo->depth, mm, mv);
900     GXLoadTexMtxImm(mv, GX_TEXMTX0, GX_MTX3x4);
901     // Tex coord generation for shadow map projection
902     MTXConcat(tmo->texProj, mm, mv);
903     GXLoadTexMtxImm(mv, GX_TEXMTX1, GX_MTX3x4);
904 }
905 
906 /*---------------------------------------------------------------------------*
907     Name:           SetCamera
908 
909     Description:    set view matrix and load projection matrix into hardware
910 
911     Arguments:      cam : pointer to the MyCameraObj structure
912 
913     Returns:        none
914  *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)915 static void SetCamera( MyCameraObj* cam )
916 {
917     f32  r_theta, r_phi;
918 
919     r_theta = (f32)cam->theta * PI / 180.0F;
920     r_phi   = (f32)cam->phi   * PI / 180.0F;
921 
922     cam->cfg.location.x =
923         cam->distance * cosf(r_theta) * cosf(r_phi);
924     cam->cfg.location.y =
925         cam->distance * sinf(r_theta) * cosf(r_phi);
926     cam->cfg.location.z =
927         cam->distance * sinf(r_phi);
928 
929     MTXLookAt(
930         cam->view,
931         &cam->cfg.location,
932         &cam->cfg.up,
933         &cam->cfg.target );
934 
935     if ( cam->cfg.type == GX_PERSPECTIVE )
936     {
937         MTXFrustum(
938             cam->proj,
939             cam->cfg.top,
940             - (cam->cfg.top),
941             cam->cfg.left,
942             - (cam->cfg.left),
943             cam->cfg.znear,
944             cam->cfg.zfar );
945     }
946     else // ( cam->cfg.type == GX_ORTHOGRAPHIC )
947     {
948         MTXOrtho(
949             cam->proj,
950             cam->cfg.top,
951             - (cam->cfg.top),
952             cam->cfg.left,
953             - (cam->cfg.left),
954             cam->cfg.znear,
955             cam->cfg.zfar );
956     }
957 
958     GXSetProjection(cam->proj, cam->cfg.type);
959 }
960 
961 /*---------------------------------------------------------------------------*
962     Name:           GetTexProjMtx
963 
964     Description:    Sets texture coord generation matrix for shadow
965                     projection and depth value lookup
966 
967     Arguments:      tmo : MyTransMtxObj structure in which generated
968                               texgen matrices should be set
969                     cam : camera from a light for projection
970                     bitMode : shadow depth precision mode
971                               0 - 8bit / 1 - 16bit
972 
973     Returns:        none
974  *---------------------------------------------------------------------------*/
GetTexProjMtx(MyTransMtxObj * tmo,MyCameraObj * cam,u8 bitMode)975 static void GetTexProjMtx( MyTransMtxObj* tmo, MyCameraObj* cam, u8 bitMode )
976 {
977     f32 n, f, range, tscale;
978     Mtx proj, dp;
979 
980     n = cam->cfg.znear;
981     f = cam->cfg.zfar;
982     range = f - n;
983 
984     // Make a zero matrix
985     MTXScale(dp, 0.0F, 0.0F, 0.0F);
986 
987     // Precision control
988     tscale = ( bitMode ) ? 256.0F : 16.0F;
989 
990     if ( cam->cfg.type == GX_PERSPECTIVE )
991     {
992         // Shadow projection matrix
993         MTXLightFrustum(
994             proj,
995             - (cam->cfg.top), // t = -y in projected texture
996             cam->cfg.top,
997             cam->cfg.left,
998             - (cam->cfg.left),
999             cam->cfg.znear,
1000             0.50F,
1001             0.50F,
1002             0.50F,
1003             0.50F );
1004 
1005         // Depth lookup matrix
1006         // in order to generate:
1007         //     s = (1 + N/z) * F / (F - N)
1008         //     t = s * tscale due to the texture size
1009         MTXRowCol(dp, 0, 2) = f / range;
1010         MTXRowCol(dp, 0, 3) = f * n / range;
1011         MTXRowCol(dp, 1, 2) = MTXRowCol(dp, 0, 2) * tscale;
1012         MTXRowCol(dp, 1, 3) = MTXRowCol(dp, 0, 3) * tscale;
1013         MTXRowCol(dp, 2, 2) = 1.0F;
1014     }
1015     else // ( cam->cfg.type == GX_ORTHOGRAPHIC )
1016     {
1017         // Shadow projection matrix
1018         MTXLightOrtho(
1019             proj,
1020             - (cam->cfg.top), // t = -y in projected texture
1021             cam->cfg.top,
1022             cam->cfg.left,
1023             - (cam->cfg.left),
1024             0.50F,
1025             0.50F,
1026             0.50F,
1027             0.50F );
1028 
1029         // Depth lookup matrix
1030         // in order to generate:
1031         //     s = - (z + N) / (F - N)
1032         //     t = s * tscale due to the texture size
1033         MTXRowCol(dp, 0, 2) = - 1.0F / range;
1034         MTXRowCol(dp, 0, 3) = - n / range;
1035         MTXRowCol(dp, 1, 2) = MTXRowCol(dp, 0, 2) * tscale;
1036         MTXRowCol(dp, 1, 3) = MTXRowCol(dp, 0, 3) * tscale;
1037         MTXRowCol(dp, 2, 3) = 1.0F;
1038     }
1039 
1040     MTXConcat(proj, cam->view, tmo->texProj);
1041     MTXConcat(dp,   cam->view, tmo->depth);
1042 }
1043 
1044 /*---------------------------------------------------------------------------*
1045     Name:           SetLight
1046 
1047     Description:    Set up light parameters
1048 
1049     Arguments:      light : pointer to a MyLightObj structure
1050                     v     : view matrix
1051 
1052     Returns:        none
1053  *---------------------------------------------------------------------------*/
SetLight(MyLightObj * light,Mtx v)1054 void SetLight( MyLightObj* light, Mtx v )
1055 {
1056     Vec lpos = light->cam.cfg.location;
1057 
1058     // Multiplied by view matrix
1059     MTXMultVec(v, &lpos, &lpos);
1060 
1061     GXInitLightPos(&light->lobj, lpos.x, lpos.y, lpos.z);
1062     GXInitLightColor(&light->lobj, COL_LIGHT);
1063     GXLoadLightObjImm(&light->lobj, GX_LIGHT0);
1064 }
1065 
1066 /*---------------------------------------------------------------------------*
1067     Name:           SetShaderModeFor1stPass
1068 
1069     Description:    Set up shading mode (color channel, TEV, etc.)
1070                     for 1st pass which generates shadow depth map.
1071                     Actually this pass requires only position data.
1072 
1073     Arguments:      none
1074 
1075     Returns:        none
1076  *---------------------------------------------------------------------------*/
SetShaderModeFor1stPass(void)1077 void SetShaderModeFor1stPass( void )
1078 {
1079     GXSetNumChans(1);
1080     GXSetChanCtrl(
1081         GX_COLOR0A0,
1082         GX_DISABLE,    // disable channel
1083         GX_SRC_REG,    // amb source
1084         GX_SRC_REG,    // mat source
1085         GX_LIGHT_NULL, // light mask
1086         GX_DF_CLAMP,   // diffuse function
1087         GX_AF_NONE );
1088 
1089     GXSetNumTevStages(1);
1090     GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
1091     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL,
1092                   GX_TEXMAP_NULL, GX_COLOR0A0);
1093 
1094     GXSetNumTexGens(0);
1095 }
1096 
1097 /*---------------------------------------------------------------------------*
1098     Name:           SetShaderModeFor2ndPass8
1099 
1100     Description:    Set up shading mode (color channel, TEV, etc.)
1101                     for 2nd pass which draws actual scene from the
1102                     viewer with full-scene shadow.
1103 
1104                     [ 8bit precision comparison version ]
1105 
1106     Arguments:      none
1107 
1108     Returns:        none
1109  *---------------------------------------------------------------------------*/
SetShaderModeFor2ndPass8(void)1110 void SetShaderModeFor2ndPass8( void )
1111 {
1112     GXSetNumChans(1);
1113     GXSetChanCtrl(
1114         GX_COLOR0A0,
1115         GX_ENABLE,     // enable channel
1116         GX_SRC_REG,    // amb source
1117         GX_SRC_REG,    // mat source
1118         GX_LIGHT0,     // light mask
1119         GX_DF_CLAMP,   // diffuse function
1120         GX_AF_NONE );
1121     GXSetChanAmbColor(GX_COLOR0A0, COL_AMBIENT);
1122 
1123     GXSetNumTevStages(3);
1124 
1125     // TEV Stage 0  ( Loads a depth value from ramp texture )
1126     // REGPREV(C) = TEX(I)
1127     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0,
1128                   GX_TEXMAP0, GX_COLOR_NULL);
1129     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO,
1130                     GX_CC_ZERO, GX_CC_TEXC);
1131     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
1132                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1133     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
1134 
1135     // TEV Stage 1  ( Compare with shadow map texture )
1136     // REGPREV = ( REGPREV > shadow map texture(R) ? 255 : 0 )
1137     GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1,
1138                   GX_TEXMAP1, GX_COLOR_NULL);
1139     GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_TEXC,
1140                     GX_CC_ONE, GX_CC_ZERO);
1141     GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_COMP_R8_GT, GX_TB_ZERO,
1142                     GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV);
1143     GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0);
1144 
1145     // TEV Stage 2  ( Select shadow/lit color )
1146     // output = ( REGPREV == 0 ? rasterized color : shadow color )
1147     // Register 0 is supporsed to hold shadow color
1148     GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD_NULL,
1149                   GX_TEXMAP_NULL, GX_COLOR0A0);
1150     GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_RASC, GX_CC_C0,
1151                     GX_CC_CPREV, GX_CC_ZERO);
1152     GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO,
1153                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1154     GXSetTevSwapMode(GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0);
1155 
1156     // Tex coords
1157     GXSetNumTexGens(2);
1158     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
1159     GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX1);
1160 }
1161 
1162 /*---------------------------------------------------------------------------*
1163     Name:           SetShaderModeFor2ndPass16
1164 
1165     Description:    Set up shading mode (color channel, TEV, etc.)
1166                     for 2nd pass which draws actual scene from the
1167                     viewer with full-scene shadow.
1168 
1169                     [ 16bit precision comparison version ]
1170 
1171     Arguments:      none
1172 
1173     Returns:        none
1174  *---------------------------------------------------------------------------*/
SetShaderModeFor2ndPass16(void)1175 void SetShaderModeFor2ndPass16( void )
1176 {
1177     GXColor col_one = { 1, 1, 1, 1 };
1178 
1179     GXSetNumChans(1);
1180     GXSetChanCtrl(
1181         GX_COLOR0A0,
1182         GX_ENABLE,     // enable channel
1183         GX_SRC_REG,    // amb source
1184         GX_SRC_REG,    // mat source
1185         GX_LIGHT0,     // light mask
1186         GX_DF_CLAMP,   // diffuse function
1187         GX_AF_NONE );
1188     GXSetChanAmbColor(GX_COLOR0A0, COL_AMBIENT);
1189 
1190     GXSetNumTevStages(3);
1191 
1192     // Make a swap table which performs A->G, I->R conversion
1193     GXSetTevSwapModeTable(GX_TEV_SWAP1,
1194                           GX_CH_RED,  GX_CH_ALPHA,
1195                           GX_CH_BLUE, GX_CH_ALPHA);
1196     // Make a swap table which performs I->G, A->R conversion
1197     GXSetTevSwapModeTable(GX_TEV_SWAP2,
1198                           GX_CH_ALPHA, GX_CH_GREEN,
1199                           GX_CH_BLUE,  GX_CH_ALPHA);
1200 
1201     // TEV Stage 0  ( Loads a depth value from ramp texture )
1202     // REGPREV(R) = TEX(I) / REGPREV(G) = TEX(A)
1203     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0,
1204                   GX_TEXMAP0, GX_COLOR_NULL);
1205     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO,
1206                     GX_CC_ZERO, GX_CC_TEXC);
1207     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
1208                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1209     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP1);
1210 
1211     // TEV Stage 1  ( Compare G+R 16bit value )
1212     // REGPREV(C) = REGPREV(GR) > shadow map texture(GR) ? 255 : 0
1213     GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1,
1214                   GX_TEXMAP1, GX_COLOR_NULL);
1215     GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_CPREV, GX_CC_TEXC,
1216                     GX_CC_ONE, GX_CC_ZERO);
1217     GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_COMP_GR16_GT, GX_TB_ZERO,
1218                     GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV);
1219     GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP2);
1220 
1221     // TEV Stage 2  ( Select shadow/lit color )
1222     // output = ( REGPREV == 0 ? rasterized color : shadow color )
1223     // Register 0 is supporsed to hold shadow color
1224     GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD_NULL,
1225                   GX_TEXMAP_NULL, GX_COLOR0A0);
1226     GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_RASC, GX_CC_C0,
1227                     GX_CC_CPREV, GX_CC_ZERO);
1228     GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO,
1229                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1230     GXSetTevSwapMode(GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0);
1231 
1232     // Tex coords
1233     GXSetNumTexGens(2);
1234     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
1235     GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX1);
1236 }
1237 
1238 /*---------------------------------------------------------------------------*
1239     Name:           SetShaderModeForProj8
1240 
1241     Description:    Set up shading mode (color channel, TEV, etc.)
1242                     for 2nd pass.
1243                     This mode displays projected shadow map only.
1244 
1245                     [ 8bit precision comparison version ]
1246 
1247     Arguments:      none
1248 
1249     Returns:        none
1250  *---------------------------------------------------------------------------*/
SetShaderModeForProj8(void)1251 void SetShaderModeForProj8( void )
1252 {
1253     GXSetNumTevStages(1);
1254 
1255     // Color mask value for displaying only red component.
1256     GXSetTevColor(GX_TEVREG1, COL_RED);
1257 
1258     // TEV stage 0 ( output = TEX(C) * TEVREG1(Red) )
1259     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
1260     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC,
1261                     GX_CC_C1, GX_CC_ZERO);
1262     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
1263                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1264 
1265     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
1266 
1267     // No color channel necessary
1268     GXSetNumChans(0);
1269 
1270     GXSetNumTexGens(1);
1271     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX1);
1272 }
1273 
1274 /*---------------------------------------------------------------------------*
1275     Name:           SetShaderModeForProj16
1276 
1277     Description:    Set up shading mode (color channel, TEV, etc.)
1278                     for 2nd pass.
1279                     This mode displays projected shadow map only.
1280 
1281                     [ 16bit precision comparison version ]
1282 
1283     Arguments:      none
1284 
1285     Returns:        none
1286  *---------------------------------------------------------------------------*/
SetShaderModeForProj16(void)1287 void SetShaderModeForProj16( void )
1288 {
1289     GXSetNumTevStages(1);
1290 
1291     // Mask color which show only Red/Green components.
1292     GXSetTevColor(GX_TEVREG1, COL_YELLOW);
1293 
1294     // Make a swap table which performs I->R, A->G conversion
1295     GXSetTevSwapModeTable(GX_TEV_SWAP1,
1296                           GX_CH_RED,   GX_CH_ALPHA,
1297                           GX_CH_BLUE,  GX_CH_ALPHA);
1298 
1299     // TEV stage 0 ( output = TEX(AII) * TEVREG1(Yellow) )
1300     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0,
1301                   GX_TEXMAP0, GX_COLOR_NULL);
1302     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C1,
1303                     GX_CC_TEXC, GX_CC_ZERO);
1304     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
1305                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1306     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP1);
1307 
1308     // No color channel necessary
1309     GXSetNumChans(0);
1310 
1311     GXSetNumTexGens(1);
1312     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX1);
1313 }
1314 
1315 /*---------------------------------------------------------------------------*
1316     Name:           SetShaderModeForDepth8
1317 
1318     Description:    Set up shading mode (color channel, TEV, etc.)
1319                     for 2nd pass.
1320                     This mode shows actual depth from the light.
1321 
1322                     [ 8bit precision version ]
1323 
1324     Arguments:      none
1325 
1326     Returns:        none
1327  *---------------------------------------------------------------------------*/
SetShaderModeForDepth8(void)1328 void SetShaderModeForDepth8( void )
1329 {
1330     GXSetNumTevStages(1);
1331 
1332     // Color mask value for displaying only red component.
1333     GXSetTevColor(GX_TEVREG1, COL_RED);
1334 
1335     // TEV stage 0 ( output = TEX(I) * TEVREG1(Red) )
1336     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0,
1337                   GX_TEXMAP0, GX_COLOR_NULL);
1338     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC,
1339                     GX_CC_C1, GX_CC_ZERO);
1340     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
1341                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1342 
1343     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
1344 
1345     // No color channel necessary
1346     GXSetNumChans(0);
1347 
1348     GXSetNumTexGens(1);
1349     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
1350 }
1351 
1352 /*---------------------------------------------------------------------------*
1353     Name:           SetShaderModeForDepth16
1354 
1355     Description:    Set up shading mode (color channel, TEV, etc.)
1356                     for 2nd pass.
1357                     This mode shows actual depth from the light.
1358 
1359                     [ 16bit precision version ]
1360 
1361     Arguments:      none
1362 
1363     Returns:        none
1364  *---------------------------------------------------------------------------*/
SetShaderModeForDepth16(void)1365 void SetShaderModeForDepth16( void )
1366 {
1367     GXSetNumTevStages(1);
1368 
1369     // Mask color which show only G/R components
1370     GXSetTevColor(GX_TEVREG1, COL_YELLOW);
1371 
1372     // Make a swap table which performs A->R, I->G conversion
1373     GXSetTevSwapModeTable(GX_TEV_SWAP1,
1374                           GX_CH_ALPHA, GX_CH_GREEN,
1375                           GX_CH_BLUE,  GX_CH_ALPHA);
1376 
1377     // TEV stage 0 ( output = TEX(AII) * TEVREG1(Yellow) )
1378     GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0,
1379                   GX_TEXMAP0, GX_COLOR_NULL);
1380     GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_C1,
1381                     GX_CC_TEXC, GX_CC_ZERO);
1382     GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
1383                     GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
1384     GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP1);
1385 
1386     // No color channel necessary
1387     GXSetNumChans(0);
1388 
1389     GXSetNumTexGens(1);
1390     GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_POS, GX_TEXMTX0);
1391 }
1392 
1393 /*---------------------------------------------------------------------------*
1394     Name:           CreateRampTex8
1395 
1396     Description:    Create a ramp texture (8bit version) which is used
1397                     to lookup depth value from a light.
1398                     This function is called only once at the beginning.
1399                     Actually you can prepare this ramp texture as static
1400                     data.
1401 
1402                     Created texture data (I8 format) is like this:
1403 
1404                     | 00 10 20 30 .... F0 |
1405                     | 01 11 21 31 .... F1 |
1406                     |  :  :  :  :       : |
1407                     | 0F 1F 2F 3F .... FF |
1408 
1409     Arguments:      to: a texture object where the texture data should be set
1410 
1411     Returns:        none
1412  *---------------------------------------------------------------------------*/
CreateRampTex8(GXTexObj * to)1413 void CreateRampTex8( GXTexObj* to )
1414 {
1415     u8*   data;
1416     u32   size, i, offset;
1417 
1418     size = GXGetTexBufferSize(16, 16, GX_TF_I8, GX_FALSE, 0);
1419     data = (u8*)MEMAllocFromAllocator(&DemoAllocator1, size);
1420 
1421     // Write ramp data pattern
1422     for ( i = 0 ; i < 0x100 ; ++i )
1423     {
1424         // I8 format tile offset
1425         offset = ((i & 0x80) >> 2)
1426                + ((i & 0x70) >> 4)
1427                + ((i & 0x0C) << 4)
1428                + ((i & 0x03) << 3);
1429         *(data+offset) = (u8)i;
1430     }
1431 
1432     // Initialize texture object properties
1433     GXInitTexObj(to, data, 16, 16, GX_TF_I8, GX_CLAMP, GX_REPEAT, GX_FALSE);
1434     GXInitTexObjLOD(to, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
1435 
1436     // Make sure data is written into the main memory.
1437     DCFlushRange(data, size);
1438 }
1439 
1440 /*---------------------------------------------------------------------------*
1441     Name:           CreateRampTex16
1442 
1443     Description:    Create a ramp texture (16bit version) which is used
1444                     to lookup depth value from a light.
1445                     This function is called only once at the beginning.
1446                     Actually you can prepare this ramp texture as static
1447                     data.
1448 
1449                     Created texture data (IA8 format) is like this:
1450 
1451                     | 0000 0100 0200 .... FF00 |
1452                     | 0001 0101 0201 .... FF01 |
1453                     |   :    :    :         :  |
1454                     | 00FF 01FF 02FF .... FFFF |
1455 
1456     Arguments:      to: a texture object where the texture data should be set
1457 
1458     Returns:        none
1459  *---------------------------------------------------------------------------*/
CreateRampTex16(GXTexObj * to)1460 void CreateRampTex16( GXTexObj* to )
1461 {
1462     u16*  data;
1463     u32   size, i, offset;
1464 
1465     size = GXGetTexBufferSize(256, 256, GX_TF_IA8, GX_FALSE, 0);
1466     data = (u16*)MEMAllocFromAllocator(&DemoAllocator1, size);
1467 
1468     // Write ramp data pattern
1469     for ( i = 0 ; i < 0x10000 ; ++i )
1470     {
1471         // IA8 format tile offset
1472         offset = ((i & 0xFC00) >> 6)
1473                + ((i & 0x0300) >> 8)
1474                + ((i & 0x00FC) << 8)
1475                + ((i & 0x0003) << 2);
1476         *(data+offset) = (u16)i;
1477     }
1478 
1479     // Initialize texture object properties
1480     GXInitTexObj(to, data, 256, 256, GX_TF_IA8, GX_CLAMP, GX_REPEAT, GX_FALSE);
1481     GXInitTexObjLOD(to, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
1482 
1483     // Make sure data is written into the main memory.
1484     DCFlushRange(data, size);
1485 }
1486 
1487 /*---------------------------------------------------------------------------*
1488     Name:           PrintIntro
1489 
1490     Description:    Prints the directions on how to use this demo.
1491 
1492     Arguments:      none
1493 
1494     Returns:        none
1495  *---------------------------------------------------------------------------*/
PrintIntro(void)1496 static void PrintIntro( void )
1497 {
1498     OSReport("\n\n");
1499     OSReport("******************************************************\n");
1500     OSReport("tg-shadow3: full-scene shadow by Z buffer copy\n");
1501     OSReport("******************************************************\n");
1502     OSReport("to quit hit the start button\n");
1503     OSReport("\n");
1504     OSReport("Main stick : Move the camera\n");
1505     OSReport("Sub  stick : Move the light\n");
1506     OSReport("A button   : Change display mode\n");
1507     OSReport("B button   : Change projection type\n");
1508     OSReport("Y button   : Change shadow map size\n");
1509     OSReport("******************************************************\n");
1510     OSReport("\n\n");
1511 }
1512 
1513 /*============================================================================*/
1514