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