gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > Ortho Z-Fighting

#107150 - Goosey - Fri Oct 27, 2006 6:55 am

Been banging my head on this all night..

I am using orthographic projection in a 2 quad test case. When the 'front' quad moved below the 'back' quad on the y axis it would be drawn behind, otherwise drawn in front.

I recreated this demo using perspective mode and found I could recreate the 'flicker' effect if I set both quads to the same Z-depth. This leads me to believe this is how the DS handles z-fighting (low the scanline the poly reaches, the sooner it is drawn). The odd thing about this all is that changing the Z-Depth in orthographic mode did not make the flickering stop.

NOTE: this is a problem appear only on hardware, emulators are not showing this behavior.

Here is an *.nds for the ortho:
www.goosey.info/temp/wtf_Ortho.nds

Here is an *.nds for the perspective:
www.goosey.info/temp/wtf_Persp.nds

Controls for both:
- arrows - move jet
- l/r - rotate jet (this can cause flicker if rotations cause it to go 'south' of the drunken coders quad).
- y/x - change jet z-depth
- a/b - change drunken z-depth

( same controls )

I am pretty fucking stumped, any ideas?

Things I did look at:
- The ortho appears to not 'squish' z as I thought for a bit, i set up the camera to look at it from an angle and z obviously effected something.
- Changing the draw order doesn't solve this issue (jet is drawn second in those demos tho)
- :(

Ill post code tomorrow (making this post quickly as security shoos the students out, building closing for the night).

#107274 - Goosey - Sat Oct 28, 2006 4:34 am

Here is the code for the Ortho

Code:


#include "ARM9Common.h"

#include "texture_bin.h"
#include "OrangeJet_bin.h"

//-------------------------------------------------------------------------------
int main( void ) {

   powerON(POWER_ALL);

   //---------------------------------------------------------------------------------
   // initialize the irq dispatcher
   ForceIrqInit();

   FIFOCommand9::Init();

   // a vblank interrupt is needed to use swiWaitForVBlank()
   // since the dispatcher handles the flags no handler is required
   irqEnable(IRQ_VBLANK);
   videoSetMode(MODE_0_3D);   // 3d on main screen
   videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE);   //sub bg 0 will be used to print text

   vramSetBankC(VRAM_C_SUB_BG);

   SUB_BG0_CR = BG_MAP_BASE(31);

   BG_PALETTE_SUB[255] = RGB15(31,31,31);   //by default font will be rendered with color 255

   // consoleInit() is a lot more flexible but this gets you up and running quick
   consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(31), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);

   float rZ = 0.0;
   float z1   = 0;
   float z2   = 0;
   int x      = 0;
   int y      = 0;
   int width   = 128;
   int height   = 128;

   //this should work the same as the normal gl call
   glViewPort(0,0,255,191);

   glClearColor(0,0,0);
   glClearDepth(0x7FFF);

   vramSetBankA(VRAM_A_TEXTURE);

   int textureID[2];
   glGenTextures(2, textureID);
   glBindTexture(GL_TEXTURE_2D, textureID[0]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXTURE_SIZE_64 , TEXTURE_SIZE_64, 0, TEXGEN_TEXCOORD, (u8*)OrangeJet_bin);

   glBindTexture(GL_TEXTURE_2D, textureID[1]);
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXTURE_SIZE_128 , TEXTURE_SIZE_128, 0, TEXGEN_TEXCOORD, (u8*)texture_bin);

#define transX(x) (inttov16(x)>>6)
#define transY(y) (inttov16(y)>>6)
#define glVertex2v16_Ortho(xg,yg,zz) glVertex3v16(transX(xg), transY(yg), floattov16(zz) );
#define glTextureCoord2t16_Ortho(u,v) glTexCoord2t16(v,u);

   forever()
   {
      // Scan keys for input
      scanKeys();
      u16 keys = keysHeld();
      if((keys & KEY_R))      rZ += 3;
      if((keys & KEY_L))      rZ -= 3;
      if((keys & KEY_X))      z1 += 0.05;
      if((keys & KEY_Y))      z1 -= 0.05;
      if((keys & KEY_A))      z2 += 0.05;
      if((keys & KEY_B))      z2 -= 0.05;
      if((keys & KEY_UP))      y -= 1;
      if((keys & KEY_DOWN))   y += 1;
      if((keys & KEY_LEFT))   x -= 1;
      if((keys & KEY_RIGHT))   x += 1;      

      printf("x:%d y:%d rZ:%f\n drunkZ:%f jetZ:%f\n", x, y, rZ, z1, z2);

      glReset(); // Must be per-frame
      glEnable(GL_ALPHA_TEST);
      glOrtho(0, 4,      3, 0,      1, -1);

      glPushMatrix();

      glMatrixMode(GL_TEXTURE);
      glIdentity();
      glMatrixMode(GL_MODELVIEW);
      
      //draw the objects
      glPushMatrix();
      glBindTexture(GL_TEXTURE_2D, textureID[1]);
      glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_ID(0));
      glBegin(GL_QUAD);
      {
         glColor3b(0,255,255);

         glTextureCoord2t16_Ortho(0,0);
         glVertex2v16_Ortho(50,   50,         z1);

         glTextureCoord2t16_Ortho(inttot16(128), 0);
         glVertex2v16_Ortho(150,      50,      z1);

         glTextureCoord2t16_Ortho(inttot16(128),inttot16(128));
         glVertex2v16_Ortho(150,      150,   z1);

         glTextureCoord2t16_Ortho(0, inttot16(128));
         glVertex2v16_Ortho(50,   150,      z1);
      }
      glEnd();
      glPopMatrix(1);

      glPushMatrix();
      glTranslate3f32(inttof32( x )>>6, inttof32( y )>>6, floattof32(0));
      glRotateZ(rZ);
      glBindTexture(GL_TEXTURE_2D, textureID[0]);
      glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_ID(1));
      glBegin(GL_QUAD);
      {
         glColor3b(255,0,0);

         float depth = 0.0;

         glTextureCoord2t16_Ortho(0,0);
         glVertex2v16_Ortho(-width/2,   -height/2,   z2);

         glTextureCoord2t16_Ortho(inttot16(64), 0);
         glVertex2v16_Ortho(width/2,      -height/2,   z2);

         glTextureCoord2t16_Ortho(inttot16(64),inttot16(64));
         glVertex2v16_Ortho(width/2,      height/2,   z2);

         glTextureCoord2t16_Ortho(0, inttot16(64));
         glVertex2v16_Ortho(-width/2,   height/2,   z2);
      }
      glEnd();
      glPopMatrix(1);


      glFlush();

      swiWaitForVBlank();
   }

   return 0;
}

#108136 - ollhak - Sun Nov 05, 2006 6:59 pm

Guess this thread is a few days old but anyway...

Goosey, I tried setting up the perspective in the way you showed but for some reason the quads are sometimes scaled by a pixel in the y-direction (64x63 instead of 64x64) - rounding error maybe? Have you noticed this when you try the code?

#108165 - Goosey - Mon Nov 06, 2006 2:15 am

Can't say I noticed this ollhak. Have decided to just use perspective mode and hope it will allow me to do some cool effects, so havn't been looking too closely at it.

#108206 - ollhak - Mon Nov 06, 2006 6:58 pm

Alright, I found the problem. Not really sure how to handle it gracefully though :/

It's a rounding error in the glOrthof32-function,

Quote:

MATRIX_LOAD4x4 = divf32(inttof32(2), top - bottom);


In this case, it divides 2 by -3 and the result is trucated to -2730 - which should have been -2731.

My hacky solution for the moment is this:

Quote:

MATRIX_LOAD4x4 = -1 + divf32(inttof32(2), top - bottom);


...which seems to work well with positive coordinates but not so great when the objects move into negative coordinates. A 64x64-quad at the coordinates (x, -64) should be completely out of the screen, but it isn't - one row is still displayed as if it was at (x, -63).. not sure how to fix this except for another hacky solution - moving up the origin by say 256 pixels so no object can be in negative y-space. Meh.

#108275 - Sunray - Tue Nov 07, 2006 10:56 am

Huh, why bother with floats? :)

To draw a fullscreen quad:
Code:

glReset();
glMatrixMode(GL_PROJECTION);
glOrthof32(0, 256, 192, 0, Z_NEAR, Z_FAR);
glMatrixMode(GL_MODELVIEW);
...
glBegin(GL_QUAD);
glVertex3v16(0, 0, 0);
glVertex3v16(0, 192, 0);
glVertex3v16(256, 192, 0);
glVertex3v16(256, 0, 0);
glEnd();

#108433 - ollhak - Wed Nov 08, 2006 7:37 pm

Thanks sunray, works like a charm.

Another thing, depth testing works just fine if you replace glFlush() with GFX_FLUSH = 0;