1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: tg-emboss.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 #include <demo.h>
14 #include <math.h>
15 #include "cmn-model.h"
16
17 #define SCREEN_DEPTH 128.0f
18 #define SCREEN_ZNEAR 0.0f // near plane Z in screen coordinates
19 #define SCREEN_ZFAR 1.0f // far plane Z in screen coordinates
20 #define ZBUFFER_MAX 0x00ffffff
21
22 /*---------------------------------------------------------------------------*
23 Typedefs
24 *---------------------------------------------------------------------------*/
25 typedef struct
26 {
27 Camera* camera;
28 ViewPort* viewport;
29 GXColor* bgcolor;
30 } Scene;
31
32 /*---------------------------------------------------------------------------*
33 Forward references
34 *---------------------------------------------------------------------------*/
35 void SceneDraw ( Scene* );
36 void SceneControl ( Scene*, DEMOPadStatus* );
37 void myInitModel ( void );
38 void myAnimeModel ( Scene*, DEMOPadStatus* );
39 void myDrawModel ( Scene* );
40 void myInfoModel ( Scene* );
41 static void PrintIntro( void );
42
43 /*---------------------------------------------------------------------------*
44 Rendering parameters
45 *---------------------------------------------------------------------------*/
46 Camera myCamera =
47 {
48 { 0.0f,-300.0f, 0.0f }, // position
49 { 0.0f, 0.0f, 0.0f }, // target
50 { 0.0f, 0.0f, 1.0f }, // upVec
51 33.3f, // fovy
52 16.0f, // near plane Z in camera coordinates
53 1024.0f, // far plane Z in camera coordinates
54 };
55
56 ViewPort myViewPort = { 0, 0, 0, 0 };
57 GXColor myBgColor = { 32, 32, 255, 255};
58 Scene myScene = { &myCamera, &myViewPort, &myBgColor };
59
60 /*---------------------------------------------------------------------------*
61 Application main loop
62 *---------------------------------------------------------------------------*/
main(void)63 void main ( void )
64 {
65 GXRenderModeObj *rmp;
66
67 // initialize render settings and set clear color for first frame
68 DEMOInit(NULL);
69
70 OSReport("\n\n");
71 OSReport("**********************************************\n");
72 OSReport("tg-emboss: Emboss Texture demo\n");
73 OSReport("**********************************************\n");
74 OSReport("To quit hit the start button.\n");
75 OSReport("\n");
76 OSReport("Main stick moves light position.\n");
77 OSReport("A button changes the indicated parameter.\n");
78 OSReport("B/X buttons move the parameter cursor.\n");
79 OSReport("**********************************************\n");
80 OSReport("\n\n");
81
82 GXInvalidateTexAll( );
83 GXSetCopyClear( *(myScene.bgcolor), GX_MAX_Z24 );
84
85 // Dummy copy operation to clear the eFB by specified color
86 GXCopyDisp( DEMOGetCurrentBuffer(), GX_TRUE );
87
88 rmp = DEMOGetRenderModeObj();
89 myViewPort.width = (s16) rmp->fbWidth;
90 myViewPort.height = (s16) rmp->efbHeight;
91
92 myInitModel( );
93
94 while ( ! ( DEMOPadGetButton(0) & PAD_BUTTON_MENU ) )
95 {
96 // get pad status
97 DEMOPadRead( );
98
99 // General control & model animation
100 SceneControl( &myScene, &DemoPad[0] );
101 myAnimeModel( &myScene, &DemoPad[0] );
102
103 // Draw scene
104 DEMOBeforeRender( );
105 SceneDraw( &myScene );
106 DEMODoneRender( );
107 }
108
109 OSHalt("End of demo");
110 }
111
112 /*---------------------------------------------------------------------------*
113 Functions
114 *---------------------------------------------------------------------------*/
115
116 //============================================================================
117 // Scene
118 //============================================================================
119
120 /*---------------------------------------------------------------------------*
121 Name: SceneControl
122 Description: user interface for parameter control
123 Arguments:
124 Returns: none
125 *---------------------------------------------------------------------------*/
SceneControl(Scene * s,DEMOPadStatus * pad)126 void SceneControl( Scene* s, DEMOPadStatus* pad )
127 {
128 #pragma unused( s, pad )
129 return;
130 }
131
132 /*---------------------------------------------------------------------------*
133 Name: SceneDraw
134 Description: Draw model
135 Arguments: Scene* s
136 Returns: none
137 *---------------------------------------------------------------------------*/
SceneDraw(Scene * s)138 void SceneDraw( Scene* s )
139 {
140 Camera* c = s->camera;
141 ViewPort* v = s->viewport;
142 float aspect = (float) (4.0 / 3.0);
143
144 // Set projection matrix
145 MTXPerspective ( c->projMtx, c->fovy, aspect, c->znear, c->zfar );
146 GXSetProjection( c->projMtx, GX_PERSPECTIVE );
147
148 // Set CameraView matrix
149 MTXLookAt( c->viewMtx, &c->position, &c->up, &c->target );
150
151 // Set Viewport
152 GXSetViewport( v->xorg, v->yorg, v->width, v->height,
153 SCREEN_ZNEAR, SCREEN_ZFAR );
154 GXSetScissor ( v->xorg, v->yorg, v->width, v->height );
155
156 // Set rendering mode
157 GXSetCullMode ( GX_CULL_BACK );
158
159 // Draw objects
160 myDrawModel( s );
161
162 // draw information
163 myInfoModel( s );
164 return;
165 }
166
167 //============================================================================
168 // Model
169 // Rectangles
170 //============================================================================
171 typedef struct
172 {
173 GXColor color;
174 Point3d pos; // in world space
175 f32 dist;
176 GXLightObj obj;
177 } MyLight;
178
179 typedef struct
180 {
181 Mtx modelMtx;
182 u8 bumpScale; // 0-128 on Emulator, 0-255 on HW
183 s32 invNrmScale;
184 s32 blendSteps;
185 u32 texNo;
186 GXTexObj texObj;
187 } MyModel;
188
189 typedef struct
190 {
191 s32 cursor;
192 s32 animation;
193 GXTexCoordID coord, coord1; // to show all tex coord pairs work
194 } MyControl;
195
196 MyLight myLight;
197 MyModel myModel;
198 MyControl myControl;
199 TPLPalettePtr texPalette = 0;
200
201 #ifndef M_SQRT3
202 #define M_SQRT3 1.732050808f
203 #endif
204
205 /*---------------------------------------------------------------------------*
206 Name: myDrawModel
207 Description: draw model
208 Arguments: Camera *c
209 Returns: none
210 *---------------------------------------------------------------------------*/
myInitModel(void)211 void myInitModel( void )
212 {
213 Vec axis = { 1.0f, 0.0f, 1.0f };
214
215 //------------------------------------------------------------------------
216 // MODEL
217 //------------------------------------------------------------------------
218
219 // Matrix
220 MTXRotAxisDeg( myModel.modelMtx, &axis, -150.0f );
221
222 // Texture
223 myModel.texNo = 1;
224 TPLGetPalette( &texPalette, "gxTests/tg-02.tpl" );
225 TPLGetGXTexObjFromPalette( texPalette, &myModel.texObj, myModel.texNo-1 );
226
227 // Bump Mapping
228 myModel.bumpScale = 128;
229 myModel.blendSteps = 3;
230 myModel.invNrmScale = 48;
231
232 //------------------------------------------------------------------------
233 // LIGHT
234 //------------------------------------------------------------------------
235
236 // Light color
237 myLight.color.r = 32;
238 myLight.color.g = 64;
239 myLight.color.b = 96;
240
241 // Light position in world space
242 myLight.dist = 100.0f;
243 myLight.pos.x = - myLight.dist * 1.0f / M_SQRT3;
244 myLight.pos.y = - myLight.dist * 1.0f / M_SQRT3;
245 myLight.pos.z = + myLight.dist * 1.0f / M_SQRT3;
246
247 // Set white light with no attenuation
248 GXInitLightSpot ( &myLight.obj, 0.0f, GX_SP_OFF );
249 GXInitLightDistAttn( &myLight.obj, 0.0f, 0.0f, GX_DA_OFF );
250
251 //------------------------------------------------------------------------
252 // CONTROL
253 //------------------------------------------------------------------------
254 myControl.cursor = 0;
255 myControl.animation = 1;
256 myControl.coord = GX_TEXCOORD0;
257 myControl.coord1 = GX_TEXCOORD1;
258 }
259
260 /*---------------------------------------------------------------------------*
261 Name: myAnimeModel
262 Description: animate model
263 Arguments: Scene *s
264 Returns: none
265 *---------------------------------------------------------------------------*/
myAnimeModel(Scene * s,DEMOPadStatus * pad)266 void myAnimeModel( Scene* s, DEMOPadStatus* pad )
267 {
268 # pragma unused(s)
269 f32 r2, y2, scale;
270 Mtx tmp;
271 Vec axis;
272
273 //---------------------------------------------------------------------
274 // Move cursor
275 //---------------------------------------------------------------------
276 if ( pad->buttonDown & PAD_BUTTON_X )
277 {
278 myControl.cursor ++;
279 }
280 if ( pad->buttonDown & PAD_BUTTON_B )
281 {
282 myControl.cursor += 4;
283 }
284 myControl.cursor %= 5;
285
286 //---------------------------------------------------------------------
287 // Cycle though all texture coordinates
288 //---------------------------------------------------------------------
289 if ( pad->buttonDown & PAD_BUTTON_Y )
290 {
291 myControl.coord++;
292 if (myControl.coord > GX_TEXCOORD6)
293 myControl.coord = GX_TEXCOORD0;
294 myControl.coord1 = (GXTexCoordID)(myControl.coord + 1);
295 OSReport("Using texture coord %d and %d\n",
296 myControl.coord, myControl.coord1);
297 }
298 //---------------------------------------------------------------------
299 // Change item
300 //---------------------------------------------------------------------
301 if ( pad->buttonDown & PAD_BUTTON_A )
302 {
303 switch ( myControl.cursor )
304 {
305 case 0:
306 // Texture
307 myModel.texNo %= 3;
308 myModel.texNo ++;
309 TPLGetGXTexObjFromPalette( texPalette,
310 &myModel.texObj, myModel.texNo-1 );
311 break;
312
313 case 1:
314 // Animation
315 myControl.animation ^= 1;
316 break;
317
318 case 2:
319 // Bump scale
320 myModel.bumpScale = (u8)( ( myModel.bumpScale < 128 )
321 ? myModel.bumpScale + 32 : 0 );
322 break;
323
324 case 3:
325 // Normal scale ( 8 - 96 )
326 myModel.invNrmScale %= 96;
327 myModel.invNrmScale += 8;
328 break;
329
330 case 4:
331 // Show step of blending
332 myModel.blendSteps %= 3;
333 myModel.blendSteps ++;
334 break;
335 }
336 }
337
338 //---------------------------------------------------------------------
339 // Animation
340 //---------------------------------------------------------------------
341 if ( myControl.animation )
342 {
343 axis.x = 1.0f;
344 axis.y = 2.0f;
345 axis.z = 0.5f;
346 MTXRotAxisDeg( tmp, &axis, 1.0f );
347 MTXConcat( myModel.modelMtx, tmp, myModel.modelMtx );
348 }
349
350 //---------------------------------------------------------------------
351 // Change light position
352 //---------------------------------------------------------------------
353 if ( pad->dirs & DEMO_STICK_LEFT ) myLight.pos.x -= 2.0f;
354 if ( pad->dirs & DEMO_STICK_RIGHT ) myLight.pos.x += 2.0f;
355 if ( pad->dirs & DEMO_STICK_UP ) myLight.pos.z += 2.0f;
356 if ( pad->dirs & DEMO_STICK_DOWN ) myLight.pos.z -= 2.0f;
357
358 r2 = myLight.pos.x * myLight.pos.x + myLight.pos.z * myLight.pos.z;
359 y2 = myLight.dist * myLight.dist - r2;
360
361 if ( y2 < 0 )
362 {
363 scale = myLight.dist / sqrtf(r2);
364 myLight.pos.x *= scale;
365 myLight.pos.z *= scale;
366 myLight.pos.y = 0.0f;
367 }
368 else
369 {
370 myLight.pos.y = - sqrtf(y2);
371 }
372 }
373
374 /*---------------------------------------------------------------------------*
375 Name: myDrawModel
376 Description: draw model
377 Arguments: Scene *c
378 Returns: none
379 *---------------------------------------------------------------------------*/
380
myDrawModel(Scene * s)381 void myDrawModel( Scene* s )
382 {
383 Camera* c = s->camera;
384 Mtx mvmtx, posMtx, nrmMtx;
385 Point3d lpos;
386 f32 nrmScale = 1.0f / (f32)myModel.invNrmScale;
387 GXColor color1 = {255,64,64,255};
388
389 // set a light object
390 MTXMultVec( c->viewMtx, &myLight.pos, &lpos );
391 GXInitLightPos ( &myLight.obj, lpos.x, lpos.y, lpos.z );
392 GXInitLightColor ( &myLight.obj, myLight.color );
393 GXLoadLightObjImm( &myLight.obj, GX_LIGHT0 );
394
395 // set modelview matrix
396 GXSetCurrentMtx( GX_PNMTX0 );
397
398 // Load ModelView matrix for pos/nrm into view space
399 // Note: mvmtx is uniform transformation here, then (mvmtx)^(-T) = mvmtx
400 // With bump mapping, normal must be scaled to match texel size in
401 // texture space.
402 MTXConcat ( c->viewMtx, myModel.modelMtx, mvmtx );
403 MTXScale ( posMtx, 75.0f, 75.0f, 75.0f );
404 MTXConcat ( mvmtx, posMtx, posMtx );
405 GXLoadPosMtxImm( posMtx, GX_PNMTX0 );
406 MTXScale ( nrmMtx, nrmScale, nrmScale, nrmScale );
407 MTXConcat ( mvmtx, nrmMtx, nrmMtx );
408 GXLoadNrmMtxImm( nrmMtx, GX_PNMTX0 );
409
410 // Set texture
411 GXLoadTexObj( &myModel.texObj, GX_TEXMAP0 );
412
413 // Render mode for Box
414 GXClearVtxDesc( );
415
416 // z update for 1st stage
417 GXSetZMode ( GX_TRUE, GX_LESS, GX_TRUE );
418
419 //------------------------------------------------------------------------
420 // Actual code for bump mapping on dolphin HW.
421 //------------------------------------------------------------------------
422 {
423 GXColor bumpScale;
424 u32 i;
425 GXColor white = {255,255,255,255};
426 GXColor grey = {128,128,128,128};
427
428 // Vertex component
429 GXClearVtxDesc();
430 GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
431 GXSetVtxDesc( GX_VA_NBT, GX_DIRECT );
432 GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
433
434 // Light 0 for bump mapping
435 GXSetNumChans(1); // GX_COLOR0A0
436 GXSetChanCtrl( GX_COLOR0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG,
437 GX_LIGHT0, GX_DF_CLAMP, GX_AF_NONE );
438 GXSetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG,
439 GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE );
440 GXSetChanMatColor( GX_COLOR0A0, white );
441 GXSetChanAmbColor( GX_COLOR0A0, grey );
442
443 // clear out unused tex gens
444 for (i = 0; i < myControl.coord; i++)
445 GXSetTexCoordGen( (GXTexCoordID)i, GX_TG_MTX2x4,
446 GX_TG_POS, GX_IDENTITY );
447
448 // Tex Gen
449 // GX_TEXCOORD0: Base texcoord of bump mapping
450 // GX_TEXCOORD1: Tex gen by bump mapping
451 GXSetNumTexGens((u8)(myControl.coord1+1)); // coord1 is always the max coord
452 GXSetTexCoordGen( myControl.coord, GX_TG_MTX2x4,
453 GX_TG_TEX0, GX_IDENTITY );
454 GXSetTexCoordGen( myControl.coord1, GX_TG_BUMP0,
455 (GXTexGenSrc)((u32)myControl.coord + GX_TG_TEXCOORD0),
456 GX_IDENTITY );
457
458 // Tev Order
459 // GX_TEVSTAGE0: send base texture + diffuse color
460 // GX_TEVSTAGE1: send shifted texture
461 GXSetTevOrder( GX_TEVSTAGE0,
462 myControl.coord, GX_TEXMAP0, GX_COLOR0A0 );
463 GXSetTevOrder( GX_TEVSTAGE1,
464 myControl.coord1, GX_TEXMAP0, GX_COLOR_NULL );
465
466 // Tev Register
467 // GX_TEVREG0: ( X, X, X, bumpScale )
468 bumpScale.a = myModel.bumpScale;
469 GXSetTevColor( GX_TEVREG0, bumpScale );
470
471 //
472 // In many case, bump mapping needs 3 tev stage, but here,
473 // use only 2 tev stages, since no material texture map
474 //
475 GXSetNumTevStages( 2 );
476
477 //
478 // Tev stage0
479 // Color: BumpTexture * bumpScale + DiffuseColor => R
480 // Alpha: Not used
481 //
482 GXSetTevColorIn( GX_TEVSTAGE0, GX_CC_ZERO,
483 GX_CC_TEXC, /* Bump Texture */
484 GX_CC_A0, /* BumpScale */
485 GX_CC_RASC /* Diffuse color */ );
486 GXSetTevColorOp( GX_TEVSTAGE0, GX_TEV_ADD,
487 GX_TB_ZERO,
488 GX_CS_SCALE_1,
489 GX_DISABLE,
490 GX_TEVPREV /* To next stage */ );
491
492 GXSetTevAlphaIn( GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO,
493 GX_CA_ZERO, GX_CA_ZERO );
494 GXSetTevAlphaOp( GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
495 GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );
496
497 //
498 // Tev stage1
499 // Color: ShiftTexture * bumpScale * (-1) + R => R
500 // Alpha: Not used
501 //
502 GXSetTevColorIn( GX_TEVSTAGE1, GX_CC_ZERO,
503 GX_CC_TEXC, /* Shift Texture */
504 GX_CC_A0, /* BumpScale */
505 GX_CC_CPREV /* Last stage out */ );
506 GXSetTevColorOp( GX_TEVSTAGE1, GX_TEV_SUB, /* mult (-1) */
507 GX_TB_ZERO,
508 GX_CS_SCALE_1,
509 GX_ENABLE,
510 GX_TEVPREV );
511
512 GXSetTevAlphaIn( GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_ZERO,
513 GX_CA_ZERO, GX_CA_ZERO );
514 GXSetTevAlphaOp( GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO,
515 GX_CS_SCALE_1, GX_DISABLE, GX_TEVPREV );
516
517 //-------------------------------------------------
518 // Draw objects
519 //-------------------------------------------------
520 GXDrawCube( );
521 }
522
523 //-------------------------------------------------
524 // Draw light direction
525 //-------------------------------------------------
526
527 // Shade mode
528 GXSetChanCtrl ( GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG,
529 GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE );
530 GXSetChanMatColor( GX_COLOR0, color1 );
531
532 GXSetNumTexGens ( 0 );
533
534 // Tev mode
535 GXSetNumTevStages( 1 );
536 GXSetTevOrder ( GX_TEVSTAGE0,
537 GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
538 GXSetTevOp ( GX_TEVSTAGE0, GX_PASSCLR );
539
540 // Render mode
541 GXSetBlendMode ( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR );
542 GXSetZMode ( GX_TRUE, GX_LESS, GX_TRUE );
543
544 // Draw lines
545 GXClearVtxDesc ( );
546 GXSetVtxDesc ( GX_VA_POS, GX_DIRECT );
547 GXSetVtxAttrFmt ( GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0 );
548 GXLoadPosMtxImm ( c->viewMtx, GX_PNMTX0 );
549 GXBegin( GX_LINES, GX_VTXFMT1, 2 );
550 GXPosition3f32( 0.0f, 0.0f, 0.0f );
551 GXPosition3f32( myLight.pos.x, myLight.pos.y, myLight.pos.z );
552 GXEnd( );
553 GXBegin( GX_LINESTRIP, GX_VTXFMT1, 5 );
554 GXPosition3f32( myLight.pos.x+2.0f, myLight.pos.y, myLight.pos.z+2.0f );
555 GXPosition3f32( myLight.pos.x+2.0f, myLight.pos.y, myLight.pos.z-2.0f );
556 GXPosition3f32( myLight.pos.x-2.0f, myLight.pos.y, myLight.pos.z-2.0f );
557 GXPosition3f32( myLight.pos.x-2.0f, myLight.pos.y, myLight.pos.z+2.0f );
558 GXPosition3f32( myLight.pos.x+2.0f, myLight.pos.y, myLight.pos.z+2.0f );
559 GXEnd( );
560
561 return;
562 }
563
564 /*---------------------------------------------------------------------------*
565 Name: ModelDrawInfo
566 Description: Draw scene information
567 Arguments:
568 Returns: none
569 *---------------------------------------------------------------------------*/
myInfoModel(Scene * s)570 void myInfoModel( Scene* s )
571 {
572 ViewPort* v = s->viewport;
573
574 // Z mode for drawing captions
575 GXSetZMode( GX_TRUE, GX_ALWAYS, GX_TRUE );
576
577 // Draw parameters to the window
578 DEMOInitCaption( DM_FT_XLU, v->width, v->height );
579 DEMOPuts ( 10, (s16)(myControl.cursor*8+10), 0, "\x7f" );
580 DEMOPrintf( 18, 10, 0, "Texture %d", myModel.texNo );
581 DEMOPrintf( 18, 18, 0,
582 "Animation %s", myControl.animation ? "ON" : "OFF" );
583 DEMOPrintf( 18, 26, 0, "Bump scale %d", myModel.bumpScale );
584 DEMOPrintf( 18, 34, 0, "Normal scale 1/%d", myModel.invNrmScale );
585 DEMOPrintf( 18, 42, 0, "Blend steps %d", myModel.blendSteps );
586
587 return;
588 }
589
590 /*---------------------------------------------------------------------------*
591 Name: PrintIntro
592
593 Description: Prints the directions on how to use this demo.
594
595 Arguments: none
596
597 Returns: none
598 *---------------------------------------------------------------------------*/
PrintIntro(void)599 static void PrintIntro( void )
600 {
601 OSReport("\n\n");
602 OSReport("**********************************************\n");
603 OSReport("tg-emboss: demonstrate bump mapping using the \n");
604 OSReport(" embossing technique. \n");
605 OSReport("**********************************************\n");
606 OSReport("to quit hit the start button\n");
607 OSReport("\n");
608 OSReport("Main Stick : Move Light Position\n");
609 OSReport("Sub Stick : Rotate the Model\n");
610 OSReport("X/B Buttons : Select parameter\n");
611 OSReport("A Button : Change selected parameter\n");
612 OSReport("Y Button : Change texture coordinate\n");
613 OSReport("**********************************************\n");
614 }
615
616
617
618 /*======== End of tg-emboss.c ========*/
619