1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: ind-bump-st.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 /******************************************************************************
15 *
16 * (C) 1999, 2000 ARTX INC.. ALL RIGHTS RESERVED. UNPUBLISHED -- RIGHTS
17 * RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED STATES. USE OF A
18 * COPYRIGHT NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
19 * OR DISCLOSURE.
20 *
21 * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE SECRETS OF
22 * ARTX INC.. USE, DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT
23 * THE PRIOR EXPRESS WRITTEN PERMISSION OF ARTX INC..
24 *
25 * RESTRICTED RIGHTS LEGEND
26 *
27 * Use, duplication, or disclosure by the Government is subject to
28 * restrictions as set forth in subparagraph (c)(1)(ii) of the Rights
29 * in Technical Data and Computer Software clause at DFARS 252.227-7013
30 * or subparagraphs (c)(1) and (2) of Commercial Computer Software --
31 * Restricted Rights at 48 CFR 52.227-19, as applicable.
32 *
33 * ArtX Inc.
34 * 3400 Hillview Ave, Bldg 5
35 * Palo Alto, CA 94304
36 *
37 *****************************************************************************/
38
39 // Bump mapping test for bumpST method
40
41 #include <demo.h>
42 #include <math.h>
43
44 /*---------------------------------------------------------------------------*
45 Defines
46 *---------------------------------------------------------------------------*/
47
48 #define TPL_NAME "gxTests/dnt-02.tpl"
49
50 #define CAM_DIST 4 // Camera's distance from origin.
51 #define LIT_X_ANGLE 55.0f // Rotation around X for light.
52 #define LIT_Y_ANGLE 45.0f // Rotation around Y for light.
53
54 #define LIT_TEX_FMT GX_TF_IA8 // 8-bits each for diffuse and specular.
55
56 #define PI 3.14159265358979323846f
57
58 #define NRM_SCALE 0.8f
59
60 /*---------------------------------------------------------------------------*
61 Rendering parameters
62 *---------------------------------------------------------------------------*/
63
64 u16 W=640, H=448; // Display size
65 u16 IW=256, IH=256; // Indirect (bump) map size.
66 u16 TW=64, TH=64; // Light map size.
67 u16 TT=32, ST=32; // Light map tessellation
68 u16 TRS=5, TRT=3; // Material repetitions around donut.
69 u32 N1=20, N2=10; // Donut tessellation
70 f32 R1=1.0f, R2=0.5f; // Donut radii.
71
72 typedef struct
73 {
74 f32 x, y, z;
75 f32 nx, ny, nz;
76 f32 bx, by, bz;
77 f32 tx, ty, tz;
78 f32 s, t;
79 } coord;
80
81 void * lightMap;
82 GXTexObj lightMapObj, materialObj, nPtrbObj;
83
84 Mtx cameraMtx, objectMtx, lightMtx;
85
86 coord * donutData;
87
88 TPLPalettePtr tpl = NULL;
89
90 u32 sendNormal, sendBinormals, sendCoords;
91
92 /*---------------------------------------------------------------------------*
93 Forward references
94 *---------------------------------------------------------------------------*/
95
96 coord donutCoord (u32 a, u32 b, u32 N1, u32 N2, f32 R1, f32 R2);
97 void createDonut();
98 void sendVertex(coord *d);
99 void setupMatrices(void);
100 void setupSize(u16 w, u16 h);
101 void commonInit(void);
102 void updateMatrices(u32 id, Mtx obj, Mtx cam);
103 void setLight(GXLightID litID, GXChannelID diffID, GXChannelID specID,
104 Mtx obj, Mtx cam);
105 void bumpMapSetup();
106 void bumpMapSetdown();
107 void lightMapSetup();
108 void renderSetup1();
109 void renderSetup2();
110 void updateDonut(Mtx cam, f32 r1, f32 r2, f32 x, f32 y, f32 z);
111 void drawDonut();
112 void drawHemisphere();
113 void showMaps();
114 void drawScene(Mtx cam, f32 r1, f32 r2);
115 void main(void);
116 static void PrintIntro( void );
117
118 /*---------------------------------------------------------------------------*
119 Procedures
120 *---------------------------------------------------------------------------*/
121
122 // Fill out a coordinate entry for a donut vertex.
donutCoord(u32 a,u32 b,u32 N1,u32 N2,f32 R1,f32 R2)123 coord donutCoord (u32 a, u32 b, u32 N1, u32 N2, f32 R1, f32 R2)
124 {
125 coord result;
126 f32 angle1, angle2;
127
128 angle1 = (f32) a*2*PI/N1;
129 angle2 = (f32) b*2*PI/N2;
130
131 result.x = (R1 - (R2*cosf(angle2))) * cosf(angle1);
132 result.y = (R1 - (R2*cosf(angle2))) * sinf(angle1);
133 result.z = R2 * sinf(angle2);
134
135 result.nx = - cosf(angle2) * cosf(angle1);
136 result.ny = - cosf(angle2) * sinf(angle1);
137 result.nz = sinf(angle2);
138
139 result.bx = - sinf(angle1);
140 result.by = cosf(angle1);
141 result.bz = 0;
142
143 result.tx = sinf(angle2) * cosf(angle1);
144 result.ty = sinf(angle2) * sinf(angle1);
145 result.tz = cosf(angle2);
146
147 result.s = (f32) a/(f32) N1;
148 result.t = (f32) b/(f32) N2;
149
150 return result;
151 }
152
153 // Make coordinate structures for all points on the donut.
createDonut()154 void createDonut()
155 {
156 u32 i,j;
157
158 for (i=0; i<=N1; i++)
159 for (j=0; j<=N2; j++)
160 donutData[i*(N2+1) + j] = donutCoord(i, j, N1, N2, R1, R2);
161 }
162
163 // Send one vertex from the given coordinate structure, sending only
164 // the information specified in the global variables:
165 // sendNormal, sendBinormals, sendCoords.
sendVertex(coord * d)166 void sendVertex(coord *d)
167 {
168 GXPosition3f32(d->x, d->y, d->z);
169
170 if (sendNormal)
171 GXNormal3f32(d->nx, d->ny, d->nz);
172
173 if (sendNormal && sendBinormals)
174 {
175 GXNormal3f32(d->bx, d->by, d->bz);
176 GXNormal3f32(d->tx, d->ty, d->tz);
177 }
178
179 if (sendCoords)
180 GXTexCoord2f32(d->s, d->t);
181 }
182
183 // Set up static matrices
setupMatrices(void)184 void setupMatrices(void)
185 {
186 Mtx tempMtx;
187
188 MTXTrans(cameraMtx, 0, 0, -CAM_DIST);
189
190 MTXTrans(lightMtx, 0, 0, -1000); // Make light "infinite"
191 MTXRotDeg(tempMtx, 'y', -LIT_Y_ANGLE);
192 MTXConcat(lightMtx, tempMtx, lightMtx);
193 MTXRotDeg(tempMtx, 'x', -LIT_X_ANGLE);
194 MTXConcat(lightMtx, tempMtx, lightMtx);
195
196 MTXIdentity(objectMtx);
197 }
198
199 // Setup viewport, scissor, copy, etc. based on w/h.
setupSize(u16 w,u16 h)200 void setupSize(u16 w, u16 h)
201 {
202 GXSetViewport(0, 0, w, h, 0, 1);
203 GXSetScissor(0, 0, w, h);
204 GXSetDispCopySrc(0, 0, w, h);
205 GXSetDispCopyDst(w, h);
206 GXSetDispCopyYScale(1);
207 GXSetTexCopySrc(0, 0, w, h);
208 GXSetTexCopyDst(w, h, LIT_TEX_FMT, FALSE);
209 }
210
211 // Initialization routine common to all my tests.
commonInit(void)212 void commonInit(void)
213 {
214 GXColor black = {0,0,0,0};
215 DEMOInit(NULL);
216 GXInvalidateTexAll();
217 GXSetCopyClear( black, GX_MAX_Z24 );
218
219 GXSetZMode(TRUE, GX_LEQUAL, TRUE);
220 GXSetZCompLoc(TRUE);
221 GXSetCullMode(GX_CULL_BACK);
222
223 setupMatrices();
224 }
225
226 // Set up position/normal/texture matrices and load.
updateMatrices(u32 id,Mtx obj,Mtx cam)227 void updateMatrices(u32 id, Mtx obj, Mtx cam)
228 {
229 Mtx vertexMtx, normalMtx, binormalMtx;
230 Mtx normalTexMtx, binormalTexMtx, textureMtx, tempMtx;
231
232 // matrix for transforming vertices from object space to eye space.
233 MTXConcat(cam, obj, vertexMtx);
234
235 // the normal mtx starts out as the inverse transpose of the vertex mtx
236 if (!MTXInverse(vertexMtx, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
237 MTXTranspose(tempMtx, normalMtx);
238
239 // matrix for transforming normals from object space to eye space, then
240 // offset by 0.5,0.5, scale by NRM_SCALE/2.
241 MTXTrans(tempMtx, 0.5f, 0.5f, 0.0f);
242 MTXConcat(tempMtx, normalMtx, normalTexMtx);
243 MTXScale(tempMtx, NRM_SCALE/2, NRM_SCALE/2, NRM_SCALE/2);
244 MTXConcat(normalTexMtx, tempMtx, normalTexMtx);
245
246 // the binormal/tangent mtx starts out as the vertex mtx without translate
247 // it should not use the inverse transpose of the vertex mtx
248 MTXCopy(vertexMtx, binormalMtx);
249 binormalMtx[0][3] = 0.0f;
250 binormalMtx[1][3] = 0.0f;
251 binormalMtx[2][3] = 0.0f;
252
253 // matrix for transforming binormals from object space to eye space, then
254 // scale by NRM_SCALE/2.
255 MTXConcat(binormalMtx, tempMtx, binormalTexMtx);
256
257 // matrix for specifying material repetitions
258 MTXScale(textureMtx, TRS, TRT, 1.0f);
259
260 GXLoadPosMtxImm(vertexMtx, GX_PNMTX0 + id*3);
261 GXLoadNrmMtxImm(normalMtx, GX_PNMTX0 + id*3);
262 GXLoadTexMtxImm(textureMtx, GX_TEXMTX0, GX_MTX2x4);
263 GXLoadTexMtxImm(normalTexMtx, GX_TEXMTX1 + id*6, GX_MTX2x4);
264 GXLoadTexMtxImm(binormalTexMtx, GX_TEXMTX2 + id*6, GX_MTX2x4);
265 }
266
267 // Create an infinite light with diffuse and specular components.
setLight(GXLightID litID,GXChannelID diffID,GXChannelID specID,Mtx obj,Mtx cam)268 void setLight(GXLightID litID, GXChannelID diffID, GXChannelID specID,
269 Mtx obj, Mtx cam)
270 {
271 GXLightObj light;
272 Mtx tempMtx, litMtx;
273 Vec lPos = {0,0,0}, lDir = {0,0,-1};
274 GXColor color0 = {0x88,0x88,0x88,0xff};
275 GXColor color1 = {0x20,0x20,0x20,0x20};
276 GXColor color2 = {0xff,0xff,0xff,0xff};
277 GXColor color3 = {0x00,0x00,0x00,0x00};
278 GXColor color4 = {0x7f,0x7f,0x7f,0x7f};
279
280 // Calculate light position and direction.
281 if (!MTXInverse(obj, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
282 MTXConcat(cam, tempMtx, litMtx);
283 MTXMultVec(litMtx, &lPos, &lPos);
284
285 if (!MTXInverse(litMtx, tempMtx)) {ASSERTMSG(0,"Singular matrix!\n");}
286 MTXTranspose(tempMtx, litMtx);
287 MTXMultVec(litMtx, &lDir, &lDir);
288
289 // Setup light object.
290 // GXInitLightPos(&light, lPos.x, lPos.y, lPos.z);
291 GXInitSpecularDir(&light, lDir.x, lDir.y, lDir.z);
292 GXInitLightColor(&light, color0 );
293
294 // Light equation 4x^2 - 3. x=N*H.
295 GXInitLightAttn(&light, -3.0f, 0.0f, 4.0f, 1.0f, 0.0f, 0.0f);
296 GXLoadLightObjImm(&light, litID);
297
298 // Set material and ambient color.
299 GXSetChanAmbColor(diffID, color1 );
300 GXSetChanMatColor(diffID, color2 );
301 GXSetChanAmbColor(specID, color3 );
302 GXSetChanMatColor(specID, color4 );
303 }
304
305 // Initial setup for shadowing (setup texture).
bumpMapSetup(void)306 void bumpMapSetup(void)
307 {
308 u32 size;
309 f32 indMtx[2][3] = { { 0.5F, 0.0F, 0.0F, }, // Indirect "identity" mtx
310 { 0.0F, 0.5F, 0.0F, } }; // (not used)
311
312 // Pre-existing textures are in a tpl file.
313 TPLGetPalette(&tpl, TPL_NAME);
314
315 // Light Map Texture (generated)
316
317 // Allocate texture in main memory.
318 lightMap = MEMAllocFromAllocator(&DemoAllocator1, GXGetTexBufferSize(TW, TH, LIT_TEX_FMT, FALSE, 0));
319
320 // Create texture object.
321 GXInitTexObj(&lightMapObj, lightMap, TW, TH, LIT_TEX_FMT,
322 GX_CLAMP, GX_CLAMP, FALSE);
323
324 // Load object into hw. Lightmap will be TEXMAP1.
325 GXLoadTexObj(&lightMapObj, GX_TEXMAP1);
326
327 // Material Texture (pre-existing)
328
329 TPLGetGXTexObjFromPalette(tpl, &materialObj, 1);
330 GXLoadTexObj(&materialObj, GX_TEXMAP0); // Material will be TEXMAP0
331
332 // Normal Perturbation Texture (pre-existing)
333
334 TPLGetGXTexObjFromPalette(tpl, &nPtrbObj, 0);
335 GXLoadTexObj(&nPtrbObj, GX_TEXMAP2); // Normal perturbation will be TEXMAP2
336
337 // Set up texgen for rendering. The matrices can be changed per-object,
338 // but the texgen needn't change.
339 GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_TEXMTX0);
340 GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_BINRM, GX_TEXMTX2);
341 GXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TANGENT, GX_TEXMTX2);
342 GXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_NRM, GX_TEXMTX1);
343
344 // I will always use position matrix 0 for my geometry.
345 GXSetCurrentMtx(GX_PNMTX0);
346
347 // Diffuse is color 0, specular is alpha 0.
348 setLight(GX_LIGHT0, GX_COLOR0, GX_ALPHA0, lightMtx, cameraMtx);
349
350 // Set indirect matrix and scale to be "identity" for 64x64 textures.
351 GXSetIndTexMtx(GX_ITM_0, indMtx, 0);
352
353 // Alpha component in frame buffer will be written to.
354 GXSetAlphaUpdate(TRUE);
355
356 // Make a donut.
357 size = sizeof(coord) * (N1+1)*(N2+1);
358 donutData = MEMAllocFromAllocator(&DemoAllocator1, size);
359 createDonut();
360 }
361
bumpMapSetdown(void)362 void bumpMapSetdown(void)
363 {
364 TPLReleasePalette(&tpl);
365
366 MEMFreeToAllocator(&DemoAllocator1, lightMap);
367 MEMFreeToAllocator(&DemoAllocator1, donutData);
368 }
369
370 // Per-frame setup for actual render.
renderSetup1(void)371 void renderSetup1(void)
372 {
373 Mtx44 pMtx;
374
375 // Set the rendering size.
376 setupSize(W, H);
377
378 // Perspective projection
379 // Note that NEGATIVE Y is up for this demo!
380 MTXFrustum(pMtx, -1, 1, -1, 1, 1, 15);
381 GXSetProjection(pMtx, GX_PERSPECTIVE);
382
383 // Pixel format
384 GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
385 // We don't need to clear the display again
386
387 // Disable lights
388 GXSetChanCtrl(GX_COLOR0, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
389 GX_DF_NONE, GX_AF_NONE);
390 GXSetChanCtrl(GX_ALPHA0, FALSE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
391 GX_DF_NONE, GX_AF_NONE);
392 }
393
renderSetup2(void)394 void renderSetup2(void)
395 {
396 // Four tev stages, one Bump stage.
397 GXSetNumTevStages(4);
398 GXSetNumIndStages(1);
399
400 // Four texture coordinates, no colors.
401 GXSetNumTexGens(4);
402 GXSetNumChans(0);
403
404 // Indirect Stage 0 -- Sample normal perturbation map
405 GXSetIndTexOrder(GX_INDTEXSTAGE0, GX_TEXCOORD0, GX_TEXMAP2);
406 GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1);
407
408 // Stage 0 -- Save material texture
409 //
410 // TEVPREV = TEXC/TEXA
411 //
412 GXSetTevDirect(GX_TEVSTAGE0);
413 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
414 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
415
416 // Set up the indirect bump calculation for Stages 1-3
417 //
418 GXSetTevIndBumpST(GX_TEVSTAGE1, GX_INDTEXSTAGE0, GX_ITM_0);
419
420 // Stage 1 -- Accumulate binormal perturbation component in Bump
421 //
422 // TEVPREV = PREV
423 //
424 GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1,
425 (GXTexMapID)(GX_TEXMAP1|GX_TEX_DISABLE), GX_COLOR_NULL);
426 GXSetTevOp(GX_TEVSTAGE1, GX_PASSCLR);
427
428 // Stage 2 -- Accumulate tangent perturbation component in Bump
429 //
430 // TEVPREV = PREV
431 //
432 GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2,
433 (GXTexMapID)(GX_TEXMAP1|GX_TEX_DISABLE), GX_COLOR_NULL);
434 GXSetTevOp(GX_TEVSTAGE2, GX_PASSCLR);
435
436 // Stage 3 -- Add source normal in Bump. Index lightmap with result of
437 // perturbation. Apply diffuse and specular components.
438 //
439 // TEVPREVC = PREVC * TEXC + TEXA
440 // TEVPREVA = PREVA
441 //
442 GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP1, GX_COLOR_NULL);
443 GXSetTevColorIn(GX_TEVSTAGE3,
444 GX_CC_ZERO, GX_CC_CPREV, GX_CC_TEXC, GX_CC_TEXA);
445 GXSetTevAlphaIn(GX_TEVSTAGE3,
446 GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_APREV);
447 GXSetTevColorOp(GX_TEVSTAGE3,
448 GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
449 GXSetTevAlphaOp(GX_TEVSTAGE3,
450 GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, TRUE, GX_TEVPREV);
451
452
453 // Vertex packet specification -- Position, normal/tangent/binormal,
454 // and one pair of texture coordinates.
455 GXClearVtxDesc();
456 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
457 GXSetVtxDesc(GX_VA_NBT, GX_DIRECT);
458 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
459 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
460 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NBT, GX_NRM_NBT, GX_F32, 0);
461 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
462
463 sendNormal = TRUE;
464 sendBinormals = TRUE;
465 sendCoords = TRUE;
466 }
467
468 // Per-frame setup for light map.
lightMapSetup(void)469 void lightMapSetup(void)
470 {
471 Mtx44 pMtx;
472 Mtx idMtx;
473
474 // Set the rendering size.
475 setupSize(TW, TH);
476
477 // Orthographic projection
478 MTXOrtho(pMtx, -1, 1, -1, 1, 1, 15);
479 GXSetProjection(pMtx, GX_ORTHOGRAPHIC);
480
481 // Pixel format
482 GXSetPixelFmt(GX_PF_RGBA6_Z24, GX_ZC_LINEAR);
483 // don't need to re-clear, since we will overwrite everything we use
484
485 // Enable diffuse and specular lights.
486 // COLOR0 = diffuse
487 // ALPHA0 = specular
488 GXSetChanCtrl(GX_COLOR0, TRUE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
489 GX_DF_CLAMP, GX_AF_NONE);
490 GXSetChanCtrl(GX_ALPHA0, TRUE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0,
491 GX_DF_NONE, GX_AF_SPEC);
492
493 // One tev stage.
494 GXSetNumTevStages(1);
495
496 // No textures, one color.
497 GXSetNumTexGens(0);
498 GXSetNumChans(1);
499 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
500
501 // Stage 0 -- Send out rasterized color.
502 //
503 // TEVPREV = RAS
504 //
505 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
506
507 // Vertex packet specification -- Position and normal.
508 GXClearVtxDesc();
509 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
510 GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
511 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
512 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
513
514 sendNormal = TRUE;
515 sendBinormals = FALSE;
516 sendCoords = FALSE;
517
518 // Identity matrices for object and matrix.
519 MTXIdentity(idMtx);
520 updateMatrices(0, idMtx, idMtx);
521 }
522
523 // Prepare for donut drawing.
updateDonut(Mtx cam,f32 r1,f32 r2,f32 x,f32 y,f32 z)524 void updateDonut(Mtx cam, f32 r1, f32 r2, f32 x, f32 y, f32 z)
525 {
526 Mtx donutMtx, tempMtx;
527
528 // update object matrix for this donut.
529 MTXRotDeg(tempMtx, 'x', r2);
530 MTXConcat(tempMtx, objectMtx, objectMtx);
531 MTXRotDeg(tempMtx, 'y', r1);
532 MTXConcat(tempMtx, objectMtx, objectMtx);
533 MTXTrans(tempMtx, x, y, z);
534 MTXConcat(tempMtx, objectMtx, donutMtx);
535
536 // Create all other matrices derived from this object matrix.
537 updateMatrices(0, donutMtx, cam);
538 }
539
540 // Draw a donut.
drawDonut()541 void drawDonut()
542 {
543 u32 i,j;
544
545 for (i=0; i<N1; i++)
546 {
547 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (u16) ((N2+1)*2) );
548
549 for (j=0; j<=N2; j++)
550 {
551 sendVertex(&donutData[(i+1)*(N2+1) + j]);
552 sendVertex(&donutData[i*(N2+1) + j]);
553 }
554
555 GXEnd();
556 }
557 }
558
559 // Draw a tesselated square, with normals that make it look like a hemisphere.
drawHemisphere()560 void drawHemisphere()
561 {
562 u32 i, j;
563 coord c;
564
565 for (i=0; i<ST; i++)
566 {
567 GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, (u16) (TT*2 + 2));
568
569 for (j=0; j<=TT; j++)
570 {
571 c.x = ((f32) 2.0f*i/ST) - 1.0f;
572 c.y = ((f32) 2.0f*j/TT) - 1.0f;
573 c.z = -2.0f;
574 c.nx = c.x / NRM_SCALE;
575 c.ny = c.y / NRM_SCALE;
576 c.nz = c.x*c.x + c.y*c.y;
577 c.nz = c.nz < 1 ? sqrtf(1 - c.nz) : 0;
578 sendVertex(&c);
579
580 c.x = ((f32) 2.0f*(i+1)/ST) - 1.0f;
581 c.nx = c.x / NRM_SCALE;
582 c.nz = c.x*c.x + c.y*c.y;
583 c.nz = c.nz < 1 ? sqrtf(1 - c.nz) : 0;
584 sendVertex(&c);
585 }
586
587 GXEnd();
588 }
589 }
590
591 // Draw the full scene from a specific camera.
drawScene(Mtx cam,f32 r1,f32 r2)592 void drawScene(Mtx cam, f32 r1, f32 r2)
593 {
594 // Draw one donut, centered at 0,0,0, rotating at normal speed.
595 updateDonut(cam, r1, r2, 0.0f, 0.0f, 0.0f);
596 drawDonut();
597 }
598
599 // Show the generated light maps in the corners of the screen
600 // Also show bump textures
showMaps()601 void showMaps()
602 {
603 Mtx idMtx;
604 coord c;
605
606 // One tev stage.
607 GXSetNumTevStages(1);
608 GXSetNumIndStages(0);
609
610 // One texture, no color.
611 GXSetNumTexGens(1);
612 GXSetNumChans(0);
613 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP1, GX_COLOR_NULL);
614
615 // Stage 0 -- Send out texture color.
616 //
617 // TEVPREV = TEXC
618 //
619 GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
620 GXSetTevAlphaIn(GX_TEVSTAGE0,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ONE);
621
622 // Vertex packet specification -- Position and normal.
623 GXClearVtxDesc();
624 GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
625 GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
626 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
627 GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
628
629 sendNormal = FALSE;
630 sendBinormals = FALSE;
631 sendCoords = TRUE;
632
633 // Identity matrices for object and matrix.
634 MTXIdentity(idMtx);
635 GXLoadPosMtxImm(idMtx, GX_PNMTX0);
636 GXLoadTexMtxImm(idMtx, GX_TEXMTX0, GX_MTX2x4);
637
638 // Show diffuse light map
639 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
640 c.x = -1.0f;
641 c.y = -1.0f;
642 c.z = -1.0f;
643 c.s = 0.0f;
644 c.t = 0.0f;
645 sendVertex(&c);
646 c.x += (f32) TW/W*2;
647 c.s = 1.0f;
648 sendVertex(&c);
649 c.y += (f32) TH/H*2;
650 c.t = 1.0f;
651 sendVertex(&c);
652 c.x -= (f32) TW/W*2;
653 c.s = 0.0f;
654 sendVertex(&c);
655 GXEnd();
656
657 // Now show alpha (specular) map
658 GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXA);
659
660 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
661 c.x = 1.0f;
662 c.y = -1.0f;
663 c.z = -1.0f;
664 c.s = 1.0f;
665 c.t = 0.0f;
666 sendVertex(&c);
667 c.y += (f32) TH/H*2;
668 c.t = 1.0f;
669 sendVertex(&c);
670 c.x -= (f32) TW/W*2;
671 c.s = 0.0f;
672 sendVertex(&c);
673 c.y -= (f32) TH/H*2;
674 c.t = 0.0f;
675 sendVertex(&c);
676 GXEnd();
677
678 // Now show the S component of the bump map
679 GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP2, GX_COLOR_NULL);
680
681 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
682 c.x = -1.0f;
683 c.y = 1.0f;
684 c.z = -1.0f;
685 c.s = 0.0f;
686 c.t = 1.0f;
687 sendVertex(&c);
688 c.y -= (f32) IH/H;
689 c.t = 0.0f;
690 sendVertex(&c);
691 c.x += (f32) IW/W;
692 c.s = 1.0f;
693 sendVertex(&c);
694 c.y += (f32) IH/H;
695 c.t = 1.0f;
696 sendVertex(&c);
697 GXEnd();
698
699 // Now show the T component of the bump map
700 GXSetTevColorIn(GX_TEVSTAGE0,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
701
702 GXBegin(GX_QUADS, GX_VTXFMT0, 4);
703 c.x = 1.0f;
704 c.y = 1.0f;
705 c.z = -1.0f;
706 c.s = 1.0f;
707 c.t = 1.0f;
708 sendVertex(&c);
709 c.x -= (f32) IW/W;
710 c.s = 0.0f;
711 sendVertex(&c);
712 c.y -= (f32) IH/H;
713 c.t = 0.0f;
714 sendVertex(&c);
715 c.x += (f32) IW/W;
716 c.s = 1.0f;
717 sendVertex(&c);
718 GXEnd();
719 }
720
721 /*---------------------------------------------------------------------------*
722 Application main loop
723 *---------------------------------------------------------------------------*/
724
main(void)725 void main(void)
726 {
727 f32 rot1=0.0f;
728 f32 rot2=0.0f;
729
730 commonInit(); // Same init for all tests.
731
732 bumpMapSetup(); // Setup texture objects and all other static things.
733
734 // This is only done once in this test since the camera and light never
735 // change direction with respect to one another. If they ever do, the
736 // lightmap must be regenerated.
737 lightMapSetup(); // Setup for lightmap render.
738 drawHemisphere(); // Render hemisphere lightmap
739
740 GXCopyTex(lightMap, FALSE); // Copy to texture.
741 GXPixModeSync();
742
743 PrintIntro();
744
745 while(!(DEMOPadGetButton(0) & PAD_BUTTON_MENU))
746 {
747 DEMOPadRead();
748
749 rot1 = DEMOPadGetStickX(0)/10;
750 rot2 = DEMOPadGetStickY(0)/10;
751 DEMOBeforeRender();
752
753 renderSetup1(); // Setup for actual render, part 1.
754
755 showMaps(); // Show the lightmaps used
756
757 renderSetup2(); // Setup for actual render, part 2.
758
759 drawScene(cameraMtx, rot1, rot2);
760
761 DEMODoneRender();
762 }
763
764 bumpMapSetdown(); // Free memory and such.
765
766 OSHalt("End of demo");
767 }
768
769 /*---------------------------------------------------------------------------*
770 Name: PrintIntro
771
772 Description: Prints the directions on how to use this demo.
773
774 Arguments: none
775
776 Returns: none
777 *---------------------------------------------------------------------------*/
PrintIntro(void)778 static void PrintIntro( void )
779 {
780 OSReport("\n\n");
781 OSReport("************************************************\n");
782 OSReport("ind-bump-st: show indirect texture bump mapping\n");
783 OSReport("************************************************\n");
784 OSReport("to quit hit the start button\n");
785 OSReport("\n");
786 OSReport(" Stick X/Y : rotate the donut\n");
787 OSReport("************************************************\n\n");
788 }
789
790