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 > 2D over 3D with glOrtho

#114454 - Vich - Mon Jan 08, 2007 1:47 am

I'm having a problem with overlaying 2D over 3D in my application. I've tried to use my regular Windows/Linux OpenGL approach first, but that didn't work. I used Google and this forum's search but I couldn't really find NDS-OpenGL-related solutions, so this is what I do:

First I start a scene:
Code:

void GraphicsBridgeOglNds::BeginScene(bool clearBackBuffer)
{
   glReset();
   gluPerspective(35.0f, 256.0f / 192.0f, 0.1f, 100.0f);
   glColor3f(1, 1, 1);

   glLight(0, RGB15(31,31,31) , 0, floattov10(-1.0f), 0);

   glMatrixMode(GL_TEXTURE);
   glIdentity();
   glMatrixMode(GL_MODELVIEW);
   glIdentity();

   glMaterialf(GL_AMBIENT, RGB15(16,16,16));
   glMaterialf(GL_DIFFUSE, RGB15(16,16,16));
   glMaterialf(GL_SPECULAR, BIT(15) | RGB15(8,8,8));
   glMaterialf(GL_EMISSION, RGB15(16,16,16));

   glMaterialShinyness();
   
   glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE | POLY_FORMAT_LIGHT0);
}


Then I push some triangles(a piramid) in 3D:
Code:

glPushMatrix();
   glTranslate3f32(0, 0, floattof32(-4.0f));
   glBegin(GL_TRIANGLES);
      // Push some vertices...
   glEnd();
glPopMatrix(1);


Then I init 2D mode:
Code:

void GraphicsOglNds::StartGuiViewMatrix()
{
   glLoadIdentity();
   ClearDepthBuffer();

   glMatrixMode(GL_PROJECTION);
      glLoadIdentity();

   glOrtho(0, 256, 192, 0, 0, 1);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   glColor3f(1, 1, 1);
   glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);
   
   SetOptionDepthTesting(false);
}


Then I draw some 2D stuff:
Code:

   glPushMatrix();
   glTranslatef(0.0, 0.0, 0.0);
   glBegin(GL_QUADS);
      glVertex3f(-10.0, -10.0, 0.0);
      glVertex3f(10.0, -10.0, 0.0);
      glVertex3f(10.0, 10.0, 0.0);
      glVertex3f(-10.0, 10.0, 0.0);
   glEnd();
   glPopMatrix(1);


Then I finish the 2D mode:
Code:

void GraphicsOglNds::EndGuiViewMatrix()
{
   glMatrixMode(GL_PROJECTION);   
   glLoadIdentity();
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();

   SetOptionDepthTesting(true);
    SetOptionLighting(bPrevLightingState);
}


And finally I finish rendering:
Code:

void GraphicsBridgeOglNds::EndScene()
{
   glFlush();
   swiWaitForVBlank();
}


Does anyone have an idea what I do wrong?
Is it correct to draw a 2D vertex by using glVertex3f(x, y, 0) or must it be glVertex3f(x, 0, z)? (by trying the second one, the application still gives me a wrong result.

Here's a screenshot of what is shown(updated!):
http://warehouse.lifeisdigital.net/pictures/other/dsguiproblem.png

I understand that there are other ways of overlaying 2D, but I only want to work with the OpenGL implementation that is provided through libnds.


Last edited by Vich on Mon Jan 08, 2007 11:14 am; edited 3 times in total

#114458 - strager - Mon Jan 08, 2007 2:32 am

I hardly know much about 3D programming, much less on the DS, but I think your problem lies with the Z value of the vertices while in ortho-mode...
Code:
glOrtho(0, 256, 192, 0, 0, 1);

I'm not sure, but I think the last two values, 0 and 1, are the near and far Z values. Try placing your polygons with a Z value somewhere between these two values.

#114483 - Vich - Mon Jan 08, 2007 8:44 am

strager wrote:
I hardly know much about 3D programming, much less on the DS, but I think your problem lies with the Z value of the vertices while in ortho-mode...
Code:
glOrtho(0, 256, 192, 0, 0, 1);

I'm not sure, but I think the last two values, 0 and 1, are the near and far Z values. Try placing your polygons with a Z value somewhere between these two values.


I changed it to:
Code:
glOrtho(0, 256, 192, 0, -1, 1);

but that doesn't make any difference, because a Z value of 0 is still between 0 and 1, while now it is between -1 and 1.

I've also uploaded a new picture to show what happens if I try to draw a bigger quad: it gets displayed smaller.

#114528 - themadcelt - Mon Jan 08, 2007 8:20 pm

Goosey and I ran into similar issues when we were working with glOrtho. I've asked him to post his solution.

#114551 - Vich - Mon Jan 08, 2007 11:00 pm

themadcelt wrote:
Goosey and I ran into similar issues when we were working with glOrtho. I've asked him to post his solution.

Thanks a billion!

#114558 - simonjhall - Mon Jan 08, 2007 11:56 pm

I too had problems when using ortho - though I don't know if they're the same thing. In the end I just decided to use perspective with a really small fov - then everything started working as expected!
_________________
Big thanks to everyone who donated for Quake2

#114563 - Vich - Tue Jan 09, 2007 12:05 am

simonjhall wrote:
I too had problems when using ortho - though I don't know if they're the same thing. In the end I just decided to use perspective with a really small fov - then everything started working as expected!

That's a nice alternative solution!

Another solution a colleague came up with was saving the matrices on a Windows/Linux OpenGL implementation and loading it up into the DS system.

I'd still like to hear Goosey's method though.

#114565 - simonjhall - Tue Jan 09, 2007 12:10 am

The thing that I had was that the was no z-testing for me in ortho mode. Even doing the stuff detailed on nocash, I still couldn't get the z working properly. In fact it mentions that when you use orthographic mode w-buffering doesn't work properly.

I too thought about generating my own matrices or loading them from a PC :-)
_________________
Big thanks to everyone who donated for Quake2

#114601 - memoni - Tue Jan 09, 2007 10:42 am

I had problem with glOrtho too when I was making my flower thing. The solution was to use something like glOrtho(-1,1,0.75,-0.75,-1,1). That is, small range and zero at the center. I did not bother back then figure out what was the real problem.

#114603 - Vich - Tue Jan 09, 2007 11:43 am

memoni wrote:
I had problem with glOrtho too when I was making my flower thing. The solution was to use something like glOrtho(-1,1,0.75,-0.75,-1,1). That is, small range and zero at the center. I did not bother back then figure out what was the real problem.

That's a good hint, but I'm affraid that I can't use that, because the cross-platform engine I'm creating must work in a uniform way(2D coordinates in pixels, with (0,0) in the upper left corner of the screen).

#114624 - themadcelt - Tue Jan 09, 2007 4:28 pm

Since Goosey is far to busy with ... well... DS stuff, I'll post his solution.

1. Use glOrthof32(...) rather than glOrtho.
Code:
glOrthof32(0, 256, 192, 0,0, 1);

2. Use glVertex3v16(x, y, z) to push verts. Ensure you're using normal ints, rather than any fancy-pants fixed point numbers.
Code:
glVertex3v16(10, 10, 0);

3. Celebrate your new Orthographic projection.

<edit>removed the fancy-pants floating point numbers I left in the code sample. d'oh!</edit>


Last edited by themadcelt on Tue Jan 09, 2007 4:40 pm; edited 2 times in total

#114626 - Vich - Tue Jan 09, 2007 4:35 pm

themadcelt wrote:
Since Goosey is far to busy with ... well... DS stuff, I'll post his solution.

1. Use glOrthof32(...) rather than glOrtho.
Code:
glOrthof32(0, 256, 192, 0,0, 1);

2. Use glVertex3v16(x, y, z) to push verts. Ensure you're using normal ints, rather than any fancy-pants fixed point numbers.
Code:
glVertex3v16(10.0, 10.0, 0.0);

3. Celebrate your new Orthographic projection.


4. Drink some beer with themadcelt and Goosey.

Thanks a lot :D I'll be testing that tonight ^^

[edit] I wonder why there are no 2D vertex calls in the DS OpenGL function set. I can see how passing one argument less might give a bit more performance(when calling it more often for let's say a GUI implementation).
(although I know that I should use display lists when I call glVertex often)

#114648 - memoni - Tue Jan 09, 2007 7:34 pm

Quote:
I wonder why there are no 2D vertex calls in the DS OpenGL function set


If my memory serves me right... just look how the vertex calls are implemented :) Not sure if the HW requires both the registers to be set, though. You probably should at least initialize z before the first register.

#114655 - Vich - Tue Jan 09, 2007 8:51 pm

I think I'll make something like this:
#define glVertex2(x, y) glVertex3(x, y, 0)
Because that's how it should be and I won't have to reimplement it again if a real 2D call would ever be created.

glOrtho32f works fine by the way!

#115579 - Mr Snowflake - Wed Jan 17, 2007 11:22 am

Why don't you use the bitmap background of the DS. I do understand the engine is a port/should be platform independant, but using this bitmap background on the DS leaves you more vertices for the scene and should be quicker. Also, you don't have to worry about rotating the gui against the scene rotation.
_________________
http://www.mrsnowflake.be

#115580 - Vich - Wed Jan 17, 2007 11:30 am

Mr Snowflake wrote:
Why don't you use the bitmap background of the DS. I do understand the engine is a port/should be platform independant, but using this bitmap background on the DS leaves you more vertices for the scene and should be quicker. Also, you don't have to worry about rotating the gui against the scene rotation.


How would I manage to draw this over the 3D rendered scene? (let's say: drawing a white 2D quad over a white 3D triangle)
Could you provide me a minimalist code sample that does this? I would really appreciate that.

I can easily change my rendering engine for doing different rendering modes(I was planning that anyway) and the 2D drawing calls are put in the base class of the 3D system, so I could separate them also(and implement them differently, like you described).
_________________
[project website] [personal website]

#115590 - Mr Snowflake - Wed Jan 17, 2007 5:00 pm

Hehe, I would love to help you, but I don't know how to do this myself :). But according to DS Wiki every mode on the main screen has 3D with 3 background for different purposes.
_________________
http://www.mrsnowflake.be

#115594 - Vich - Wed Jan 17, 2007 6:08 pm

Mr Snowflake wrote:
Hehe, I would love to help you, but I don't know how to do this myself :). But according to DS Wiki every mode on the main screen has 3D with 3 background for different purposes.


The problem is that my 2D stuff needs to be on the foreground. But I'll investigate it later, thanks!
_________________
[project website] [personal website]

#115596 - Sausage Boy - Wed Jan 17, 2007 6:43 pm

Quote:
The problem is that my 2D stuff needs to be on the foreground.

It's just a matter of changing the priorities. I am pretty sure I did this some time ago and I've seen it in other programs, it's definitely possible.
_________________
"no offense, but this is the gayest game ever"

#115679 - Mr Snowflake - Thu Jan 18, 2007 11:04 am

Quote:
The problem is that my 2D stuff needs to be on the foreground. But I'll investigate it later, thanks!
It would be kinda strange to only use the 3 other BG's for skyboxing :).

Edit: Some strange thingy happened witht the [ quote] opening tag...
_________________
http://www.mrsnowflake.be

#146541 - a128 - Wed Dec 05, 2007 4:01 pm

This work like expected X=0,Y=0 top left X=255,Y=192 down right

Edit: currently has a bug, works only for Box(0,0,.......) and the layer seems not to work

based on code from lumiDS

Code:
static void perspective2D()
{
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

   glOrtho(0,1,1,0,0,12); //12 layers using int more using float

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void Box(int X, int Y, int XMAX,int YMAX,int32 color,int layer)
{
   glLoadIdentity();
   MATRIX_TRANSLATE=inttof32(X);
   MATRIX_TRANSLATE=inttof32(Y);
   MATRIX_TRANSLATE=inttof32(layer);

   glScalef((float)XMAX/256,(float)YMAX/192,1);
         
   glBindTexture(GL_TEXTURE_2D, 0);//no texture

   glColor(color);

//translucent
   glPolyFmt(POLY_ALPHA(15)  | POLY_CULL_NONE  );

   glBegin(GL_QUADS);
   glVertex3v16(0,0,0);
   glVertex3v16(inttof32(1),0,0);
   glVertex3v16(inttof32(1),inttof32(1),0);
   glVertex3v16(0,inttof32(1),0);
   glEnd();

}   
static void draw_box(){

   Box(0,0,255,10,RGB15(31,0,0),0);
}

#148866 - a128 - Fri Jan 11, 2008 3:57 pm

Forget the code above...this work like expected

use screen coords from 0...255 , 0...191

Note: Y ist the depth not Z


Code:
void Box(int X, int Y, int XMAX,int YMAX,int32 color,float layer)
{
        glLoadIdentity();

//find the max coord
   int32 scale=XMAX>YMAX?inttof32(XMAX):inttof32(YMAX);
   scale =divf32(scale,floattof32(7.99f));

   MATRIX_SCALE=scale;
   MATRIX_SCALE=scale;
   MATRIX_SCALE=scale;

   int32 x0=divf32(inttof32(X),scale);
   int32 y0=divf32(inttof32(Y),scale);
   int32 x1=divf32(inttof32(XMAX),scale);
   int32 y1=divf32(inttof32(YMAX),scale);

       glBindTexture(GL_TEXTURE_2D, 0);//no texture
        glColor(color);
       glPolyFmt(POLY_ALPHA(31)  | POLY_CULL_NONE  );

        int32 z=layer;

        glBegin(GL_QUADS);
        glVertex3v16(x0,y0,z);
        glVertex3v16(x1,y0,z);
        glVertex3v16(x1,y1,z);
        glVertex3v16(x0,y1,z);
        glEnd();

}


To draw a box in with 2D screen coords

1) glOrtho(0,256,192,0,-1,1);
2) Box(....)

#148939 - zefrench - Sat Jan 12, 2008 6:59 am

Perhapse the following librairy does what you are looking for?

?Library http://brunni.dev-fr.org/index.php?page=ndssoft_ulib

Seems like it is along the same area:

he 3D GPU provides additional effects over the 2D GPU, like full transparency with alpha channel (objects can blend amongst them), a larger number of sprites (up to 1536 instead of 128), no zoom or rotation limit (2x with the 2D GPU), a larger limit for the sprite size (2048x2048 instead of 64x64). It is also possible to draw primitives like lines, rectangles, etc. allowing nice effects like in Yoshi's island for example :)