1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution gx demo
3 File: tf-clip-bug.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 #include <demo.h>
15
16 // This demo illustrates the color clipping bug.
17 // It also shows the properties of the various Z-buffer modes.
18 //
19 // It draws 2 rectangles in perspective on either side of the screen.
20 // The left rectangle gets darker further away from the viewer, while
21 // the right rectangle gets brighter further away from the viewer.
22 // When the rectangles get near-clipped, the colors can flip around!
23 //
24 // In the middle are shown tags with different Z depths, with a red
25 // tag drawn a certain spacing behind each green tag.
26 // You should normally not be able to see any of the red tags, but
27 // this will change depending upon the Z-buffer mode and the tag spacing.
28 // It also changes greatly depending upon the near-plane distance!
29 //
30 // Of course, the near-plane distance also affects the clipping bug,
31 // so that is why we show the effects on the Z-buffering.
32 //
33 // Please refer to the HTML man page for this demo for more details.
34
35 /*---------------------------------------------------------------------------*
36 Model Data
37 *---------------------------------------------------------------------------*/
38
39 // Notes on vertex layout:
40 //
41 // The rectangle below represents the model being drawn.
42 // It is just a rectangle, but it can be tessellated into vertical strips.
43 // Lines 1 and 10 label the quad's corner vertex drawing order.
44 // Lines 3 and 8 label all the vertex positions.
45 //
46 // 1: 3 0
47 // 2: | . : . ; . : . |
48 // 3: 16 14 12 10 8 6 4 2 0
49 // 4: +-----------------------+
50 // 5: | |
51 // 6: | |
52 // 7: +-----------------------+
53 // 8: 17 15 13 11 9 7 5 3 1
54 // 9: | . : . ; . : . |
55 // 10: 2 1
56 //
57 // The above is for a single rectangle. We actually draw 2
58 // rectangles on the right and left sides, so we have twice as
59 // many vertices as that.
60
61 // indices for verts for drawing order at tessellation = 1, 2, 4, 8
62
63 static u8 ivert[4][32] =
64 {
65 { 0, 1, 17, 16 },
66 { 0, 1, 9, 8, 8, 9, 17, 16 },
67 { 0, 1, 5, 4, 4, 5, 9, 8, 8, 9, 13, 12, 12, 13, 17, 16 },
68 { 0, 1, 3, 2, 2, 3, 5, 4, 4, 5, 7, 6, 6, 7, 9, 8,
69 8, 9, 11, 10, 10, 11, 13, 12, 12, 13, 15, 14, 14, 15, 17, 16 }
70 };
71
72 #define IHALF 18
73
74 // verts
75
76 static s16 Vert_s16[] ATTRIBUTE_ALIGN(32) =
77 {
78 // left wall:
79 -10, 100, 100, // 0 0 0 0 0
80 -10, -100, 100, // 1 1 1 1 1
81 -10, 100, 75, // 3 4 2
82 -10, -100, 75, // 2 5 3
83 -10, 100, 50, // 3 4 7 8 4
84 -10, -100, 50, // 2 5 6 9 5
85 -10, 100, 25, // 11 12 6
86 -10, -100, 25, // 10 13 7
87 -10, 100, 0, // 3 4 7 8 15 16 8
88 -10, -100, 0, // 2 5 6 9 14 17 9
89 -10, 100, -25, // 20 19 10
90 -10, -100, -25, // 21 18 11
91 -10, 100, -50, // 11 12 24 23 12
92 -10, -100, -50, // 10 13 25 22 13
93 -10, 100, -75, // 28 27 14
94 -10, -100, -75, // 29 26 15
95 -10, 100, -100, // 3 7 15 31 16
96 -10, -100, -100, // 2 6 14 30 17
97 // right wall:
98 10, 100, 100, // 0 0 0 0 18
99 10, -100, 100, // 1 1 1 1 19
100 10, 100, 75, // 3 4 20
101 10, -100, 75, // 2 5 21
102 10, 100, 50, // 3 4 7 8 22
103 10, -100, 50, // 2 5 6 9 23
104 10, 100, 25, // 11 12 24
105 10, -100, 25, // 10 13 25
106 10, 100, 0, // 3 4 7 8 15 16 26
107 10, -100, 0, // 2 5 6 9 14 17 27
108 10, 100, -25, // 20 19 28
109 10, -100, -25, // 21 18 29
110 10, 100, -50, // 11 12 24 23 30
111 10, -100, -50, // 10 13 25 22 31
112 10, 100, -75, // 28 27 32
113 10, -100, -75, // 29 26 33
114 10, 100, -100, // 3 7 15 31 34
115 10, -100, -100, // 2 6 14 30 35
116 };
117
118 // colors
119
120 // Left wall is brighter closer to the eye,
121 // darker further from the eye.
122 // Right wall is darker closer to the eye,
123 // brighter further from the eye.
124
125 // Due to the clipping bug, they may appear the opposite way around.
126
127 static u32 Colors_u32[] ATTRIBUTE_ALIGN(32) =
128 {
129 // left wall:
130 // r g b a
131 0xc0c0c0ff, // 0 0
132 0xa0a0c0ff, // 1 1
133 0xb4b4c0ff, // 1/8 0-3 2
134 0x9c9cc0ff, // 1/8 1-2 3
135 0xa8a8c0ff, // 1/4 0-3 4
136 0x9898c0ff, // 1/4 1-2 5
137 0x9c9cc0ff, // 3/8 0-3 6
138 0x9494c0ff, // 3/8 1-2 7
139 0x9090c0ff, // 1/2 0-3 8
140 0x9090c0ff, // 1/2 1-2 9
141 0x8484c0ff, // 5/8 0-3 10
142 0x8c8cc0ff, // 5/8 1-2 11
143 0x7878c0ff, // 3/4 0-3 12
144 0x8888c0ff, // 3/4 1-2 13
145 0x6c6cc0ff, // 7/8 0-3 14
146 0x8484c0ff, // 7/8 1-2 15
147 0x8080c0ff, // 2 16
148 0x6060c0ff, // 3 17
149 // right wall:
150 // r g b a
151 0x2020c0ff, // 0 18
152 0x4040c0ff, // 1 19
153 0x2c2cc0ff, // 1/8 0-3 20
154 0x4444c0ff, // 1/8 1-2 21
155 0x3838c0ff, // 1/4 0-3 22
156 0x4848c0ff, // 1/4 1-2 23
157 0x4444c0ff, // 3/8 0-3 24
158 0x4c4cc0ff, // 3/8 1-2 25
159 0x5050c0ff, // 1/2 0-3 26
160 0x5050c0ff, // 1/2 1-2 27
161 0x5c5cc0ff, // 5/8 0-3 28
162 0x5454c0ff, // 5/8 1-2 29
163 0x6868c0ff, // 3/4 0-3 30
164 0x5858c0ff, // 3/4 1-2 31
165 0x7474c0ff, // 7/8 0-3 32
166 0x5c5cc0ff, // 7/8 1-2 33
167 0x6060c0ff, // 2 34
168 0x8080c0ff, // 3 35
169 };
170
171 /*---------------------------------------------------------------------------*
172 Application main loop
173 *---------------------------------------------------------------------------*/
174
main(void)175 void main ( void )
176 {
177 u16 button, down; // button return codes
178
179 Mtx44 pm; // projection matrix
180 Mtx cm; // camera matrix
181 Mtx vm; // view matrix
182 Mtx sm; // scale matrix
183 Mtx ym; // yet another view matrix
184
185 s16 i; // loop variable
186 s16 j; // loop variable
187 u8 tess = 0; // tessellation factor
188 u8 mode = 0; // AA/zbuffer mode
189
190 Vec vTmp = {0.0F, 0.0F, 0.0F}; // camera position
191 Vec at = {0.0F, 0.0F, -6000.0F}; // look at position
192 Vec up = {0.0F, 1.0F, 0.0F}; // camera up vector
193 f32 fovy = 90.0F; // FOV in Y direction
194 f32 near = 5.0f; // near plane distance
195
196 char nums[100]; // number string
197 GXColor green = { 0, 255, 0, 255 };
198 GXColor red = { 255, 0, 0, 255 };
199 s16 spacing = 5; // interplanar distance for Z tags
200 s16 xp, yp, zp; // Z tag position
201 f32 fi; // fractional i for distance calculation
202
203 //----------------------------------------------------------------------
204
205 // We use GXNtsc240Int since that makes it easy to change
206 // between 16-bit (AA) and 24-bit framebuffer modes.
207
208 DEMOInit(&GXNtsc240Int); // Init os, pad, gx, vi
209
210 GXSetCullMode(GX_CULL_NONE);
211
212 GXSetArray(GX_VA_POS, Vert_s16, 3*sizeof(s16));
213 GXSetArray(GX_VA_CLR0, Colors_u32, 1*sizeof(u32));
214
215 GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_S16, 0);
216 GXSetVtxAttrFmt(GX_VTXFMT1, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
217
218 DEMOLoadFont( GX_TEXMAP0, GX_TEXMTX0, DMTF_POINTSAMPLE );
219
220 MTXIdentity(sm);
221
222 OSReport("\n\n********************************\n");
223 OSReport("Running...\n\n");
224 OSReport("********************************\n");
225 OSReport("This demo shows the properties of the color clipping bug.\n");
226 OSReport("It also shows the properties of the various Z-buffer modes.\n");
227 OSReport("\n");
228 OSReport("It draws 2 rectangles in perspective on either side of the screen.\n");
229 OSReport("The left rectangle gets darker further away from the viewer, while\n");
230 OSReport("the right rectangle gets brighter further away from the viewer.\n");
231 OSReport("When the rectangles get near-clipped, the colors can flip around!\n");
232 OSReport("\n");
233 OSReport("In the middle are shown tags with different Z depths, with a red\n");
234 OSReport("tag drawn a certain spacing behind each green tag.\n");
235 OSReport("You should normally not be able to see any of the red tags, but\n");
236 OSReport("this will change depending upon the Z-buffer mode and the tag spacing.\n");
237 OSReport("It also changes greatly depending upon the near-plane distance!\n");
238 OSReport("\n");
239 OSReport("Of course, the near-plane distance also affects the clipping bug,\n");
240 OSReport("so that is why we show the effects on the Z-buffering.\n");
241 OSReport("\n");
242 OSReport("Please refer to the HTML man page for this demo for more details.\n");
243 OSReport("\n");
244
245 OSReport("Main stick - move camera\n");
246 OSReport("Sub stick - move camera in Z\n");
247 OSReport("L trigger - hold to adjust FOV with A/B buttons\n");
248 OSReport("R trigger - hold to adjust tessellation with X/Y buttons\n");
249 OSReport("A/B buttons - adjust near plane or FOV\n");
250 OSReport("X/Y buttons - adjust Z tag interplanar dist or tessellation\n");
251 OSReport("Start button - toggle 16/24-bit mode\n");
252 OSReport("********************************\n");
253 while(1)
254 {
255 DEMOPadRead();
256
257 down = DEMOPadGetButtonDown(0);
258 button = DEMOPadGetButton(0);
259
260 vTmp.x -= DEMOPadGetStickX(0) / 100.0f;
261 vTmp.y -= DEMOPadGetStickY(0) / 100.0f;
262 vTmp.z += DEMOPadGetSubStickY(0) / 100.0f;
263
264 if (button & PAD_TRIGGER_R)
265 {
266 if (down & PAD_BUTTON_X)
267 {
268 if (tess > 0)
269 tess--;
270 }
271 if (down & PAD_BUTTON_Y)
272 {
273 if (tess < 3)
274 tess++;
275 }
276 } else {
277 if (down & PAD_BUTTON_X)
278 {
279 spacing += 1;
280 if (spacing > 10)
281 spacing = 10;
282 }
283 if (down & PAD_BUTTON_Y)
284 {
285 spacing -= 1;
286 if (spacing < 1)
287 spacing = 1;
288 }
289 }
290
291
292 if (button & PAD_TRIGGER_L)
293 {
294 if (button & PAD_BUTTON_A)
295 {
296 fovy += 1.0F;
297 if (fovy > 179.0F)
298 fovy = 179.0F;
299 }
300 if (button & PAD_BUTTON_B)
301 {
302 fovy -= 1.0F;
303 if (fovy < 1.0F)
304 fovy = 1.0F;
305 }
306 } else {
307 if (button & PAD_BUTTON_A)
308 {
309 near += 0.1F;
310 if (near > 10.0F)
311 near = 10.0F;
312 }
313 if (button & PAD_BUTTON_B)
314 {
315 near -= 0.1F;
316 if (near < 0.1F)
317 near = 0.1F;
318 }
319 }
320
321 if (down & PAD_BUTTON_MENU)
322 {
323 mode++;
324 if (mode == 5)
325 mode = 0;
326 }
327
328
329 if (mode)
330 {
331 GXSetPixelFmt( GX_PF_RGB565_Z16, (GXZFmt16)(mode - 1) );
332 } else {
333 GXSetPixelFmt( GX_PF_RGB8_Z24, GX_ZC_LINEAR );
334 }
335
336 DEMOBeforeRender();
337
338 // Cancel out changes done by DEMOInitCaption (below)
339 GXSetZMode( GX_ENABLE, GX_LEQUAL, GX_TRUE);
340 GXSetNumChans(1);
341
342 // Set up projection, matrices
343 MTXPerspective(pm, fovy, 4.0F/3.0F, near, 10000);
344 GXSetProjection(pm, GX_PERSPECTIVE);
345
346 // Set up camera/view matrices
347 MTXLookAt(cm, &vTmp, &up, &at);
348
349 // If you want any viewing transforms, put them here
350 MTXCopy(cm, vm);
351 GXLoadPosMtxImm(vm, GX_PNMTX0);
352
353 // Set up for drawing walls
354 GXClearVtxDesc();
355 GXSetVtxDesc(GX_VA_POS, GX_INDEX8);
356 GXSetVtxDesc(GX_VA_CLR0, GX_INDEX8);
357
358 // Use vertex colors
359 GXSetChanCtrl(
360 GX_COLOR0A0,
361 GX_DISABLE,
362 GX_SRC_REG,
363 GX_SRC_VTX,
364 GX_LIGHT_NULL,
365 GX_DF_NONE,
366 GX_AF_NONE );
367
368 GXSetNumTexGens(0);
369 GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0 );
370 GXSetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
371
372 // Draw the walls
373 GXBegin(GX_QUADS, GX_VTXFMT1, (u16) ((1<<tess)*4*2));
374 for (i = 0; i < (1<<tess); i++)
375 {
376 for(j=0; j<4; j++) // left wall
377 {
378 GXPosition1x8( (u8) ivert[tess][i*4+j]);
379 GXColor1x8( (u8) ivert[tess][i*4+j]);
380 }
381 for(j=0; j<4; j++) // right wall
382 {
383 GXPosition1x8( (u8) (ivert[tess][i*4+j]+IHALF));
384 GXColor1x8( (u8) (ivert[tess][i*4+j]+IHALF));
385 }
386 }
387 GXEnd();
388
389 // Set up for drawing signs
390 vm[1][1] = - vm[1][1];
391
392 // Use register colors
393 GXSetChanCtrl(
394 GX_COLOR0A0,
395 GX_DISABLE,
396 GX_SRC_REG,
397 GX_SRC_REG,
398 GX_LIGHT_NULL,
399 GX_DF_NONE,
400 GX_AF_NONE );
401
402 GXSetNumTexGens(1);
403 GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0 );
404 GXSetTevOp(GX_TEVSTAGE0, GX_BLEND);
405
406 // Draw the signs
407 for (i = 1; i < 60; i++)
408 {
409 sprintf( nums, "%d00", i );
410
411 xp = (s16) ((i>9) ? -16 : -12);
412 yp = (s16) -8;
413 zp = (s16) (-i * 100);
414
415 // scale signs larger as they get further away
416 sm[0][0] = i * (5.0F / 12.0F);
417 sm[1][1] = i * (5.0F / 12.0F);
418 MTXConcat(vm, sm, ym);
419 // position signs up and down in vertical FOV
420 ym[1][3] = - i * 100 + i * i * (10.0F / 3.0F);
421 GXLoadPosMtxImm(ym, GX_PNMTX0);
422
423 // Draw green sign
424 GXSetChanMatColor(GX_COLOR0A0, green);
425 DEMOPuts( xp, yp, zp, nums );
426
427 // Adjust for red sign
428 zp -= spacing;
429 fi = i + spacing / 100.0F;
430 ym[1][3] = - fi * 100 + fi * fi * (10.0F / 3.0F);
431 GXLoadPosMtxImm(ym, GX_PNMTX0);
432
433 // Draw red sign
434 GXSetChanMatColor(GX_COLOR0A0, red);
435 DEMOPuts( xp, yp, zp, nums );
436 }
437
438 // Draw the control panel
439 DEMOInitCaption(DM_FT_OPQ, 640, 480);
440
441 sprintf(nums, "camera= [%g, %g, %g]", vTmp.x, vTmp.y, vTmp.z);
442 DEMOPuts( 24, 20, 0, nums );
443 sprintf(nums, "fovy = %g", fovy);
444 DEMOPuts( 24, 28, 0, nums );
445 sprintf(nums, "near = %g", near);
446 DEMOPuts( 24, 36, 0, nums );
447 sprintf(nums, "tess = %d", 1 << tess);
448 DEMOPuts( 24, 44, 0, nums );
449 sprintf(nums, "Z spacing = %d", spacing);
450 DEMOPuts( 24, 52, 0, nums );
451
452 switch (mode)
453 {
454 case 0: sprintf(nums, "24-bit linear mode"); break;
455 case 1: sprintf(nums, "16-bit linear mode"); break;
456 case 2: sprintf(nums, "16-bit near mode"); break;
457 case 3: sprintf(nums, "16-bit mid mode"); break;
458 case 4: sprintf(nums, "16-bit far mode"); break;
459 }
460
461 DEMOPuts( 24, 60, 0, nums );
462
463 DEMODoneRender();
464 }
465 OSHalt("End of demo");
466 }
467
468 /*===========================================================================*/
469