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