# OpenGL 2D sprites in OpenGL using 3D coordinates

## Recommended Posts

I am trying to use 2D sprites with OpenGL. This is NOT about texture mapping quads, but rather about the best ways to position sprites using 3d coordinates. I want to use the Depth buffer for ordering the sprites.
static int zPos;

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0,0,-2);

if(KeyPress(VK_UP))++zPos;
else if(KeyPress(VK_DOWN))--zPos;

glColor3f(1,0,1);
glVertex3i(0, 1,-10);
glVertex3i(0,-1,-10);
glVertex3i(-1,-1,-10);
glVertex3i(-1,1,-10);
glEnd();

for(int i=0;i<3;i++)
{

//Red
glColor3f(1,0,0);
glVertex3f(1, 1,zPos);

//Yellow
glColor3f(1,1,0);
glVertex3f(1,-1,zPos);

//Green
glColor3f(0,1,0);
glVertex3f(-1,-1,zPos);

//Blue
glColor3f(0,0,1);
glVertex3f(-1,1,zPos);
glEnd();

glTranslatef(2,0,0.1);
}


This is the little bit of code I've been experimenting with. I was thinking of using the zPos variable as like to represent layers, so that sprites with a deeper depth will go beneath and vice-versa. The problem, which is quite obvious is that the higher up sprites will be a bit bigger.... Any ideas on what to do? Is there a better way to do this ?

##### Share on other sites
You may switch to an equivalent orthogonal projection. Only perspective projection does a scaling dependent on the depth of occurance. (Perhaps some artifacts may occur if mixing two projection modes in one rendering pass.)

Else, of course a bottom-up ordered rendering would do the job, neglecting the need of different z values, but I assume you would not do so since it means to deny using the z buffer...

Also, you may specify a glScale per sprite to pre-undo the scaling. The scale factor is to be determined from the z value, of course, and to be applied to x and y elements only.

[Edited by - haegarr on December 3, 2005 7:20:33 AM]

##### Share on other sites
Ah... I dint get anything :(

Can anybody point me to some source of a 2D game done in opengl ?

Or just even give me some pointers on how to go about doing 2D in opengl..

##### Share on other sites
As haegarr stated, you want to use orthographic projection mode. Basically, the viewing volume becomes a box (instead of a cut-off pyramid), so coordinates are mapped on the screen without being scaled. Check out the red book, chapter 3. Scroll down to about halfway down the page to get to the theory and some code.

Edit: of course, if you are after billboards instead of sprites, and want to mix 2d and 3d in one environment, it's a completely different story. But I think that was not your intention?

##### Share on other sites
Or you could try my approach written in the forum FAQ.

##### Share on other sites
Quote:
 Original post by lightbringerAs haegarr stated, you want to use orthographic projection mode. Basically, the viewing volume becomes a box (instead of a cut-off pyramid), so coordinates are mapped on the screen without being scaled. Check out the red book, chapter 3. Scroll down to about halfway down the page to get to the theory and some code.Edit: of course, if you are after billboards instead of sprites, and want to mix 2d and 3d in one environment, it's a completely different story. But I think that was not your intention?

I am not after billboards ;)

Quote:
 Orthographic ProjectionWith an orthographic projection, the viewing volume is a rectangular parallelepiped, or more informally, a box (see Figure 3-13 ). Unlike perspective projection, the size of the viewing volume doesn't change from one end to the other, so distance from the camera doesn't affect how large an object appears. This type of projection is used for applications such as creating architectural blueprints and computer-aided design, where it's crucial to maintain the actual sizes of objects and angles between them as they're projected.

Is that what you were pointing me to ?

But once you call glOrtho() then only the glVertex2.... commands work right?

what would be the best near, far clipping values

[
I am not trying to mix 2d and 3d. Just a plain sprite based game :)
I would really love to see some source which showed 2d in opengl
]

P.S Thanks Dwarf with Axe for this Last post about 2D in OpenGL (so please stop!)

##### Share on other sites
Quote:
 Original post by FireNetBut once you call glOrtho() then only the glVertex2.... commands work right?

Wrong, glVertex3 commands would also work, I think you can uze the Z Value as a, well, z buffer.

Quote:
 Original post by FireNetwhat would be the best near, far clipping values

I use

glOrtho(-0.375f,width,height,-0.375f, 0.0f, 1.0f);

where width and height are the width and height of the window/screen.

Quote:
 Original post by FireNet[I am not trying to mix 2d and 3d. Just a plain sprite based game :)I would really love to see some source which showed 2d in opengl]

Here is my code for a 2D interface for my GUI library.

##### Share on other sites
Quote:
 Original post by FireNetBut once you call glOrtho() then only the glVertex2.... commands work right?
No.

All glOrtho does is create an orthographic projection matrix and multiplies the matrix on the top of the current matrix mode's stack by it. It is usually used on the projection matrix after it has been set to the identity. So in the normal usage, the only thing that changes is the projection matrix; the rest of OpenGL still works exactly the same way.

##### Share on other sites
As the others already stated, you still get to use the Z buffer with orthographic projection. The only thing that changes is how objects appear on the screen. If I understood your initial complaint, you didn't want them to scale with distance, and glOrtho() achieves that while keeping the "3D-ness" intact ^_^.

##### Share on other sites
void OGL_2D(){  int vPort[4];   glGetIntegerv(GL_VIEWPORT, vPort);   glMatrixMode(GL_PROJECTION);   glPushMatrix();   glLoadIdentity();   glOrtho(0, vPort[2], 0, vPort[3], -100, 100);   glMatrixMode(GL_MODELVIEW);   glPushMatrix();   glLoadIdentity();}void Render(){	static float zPos = 0;	if(KeyPress(VK_ESCAPE))FlagQuit();			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glLoadIdentity();        if(KeyPress(VK_UP))++zPos;        else if(KeyPress(VK_DOWN))--zPos;                        glBegin(GL_QUADS);        glColor3f(1,0,1);          glVertex3i(0, 1,-10);          glVertex3i(0,-1,-10);          glVertex3i(-1,-1,-10);          glVertex3i(-1,1,-10);         glEnd();                        for(int i=0;i<3;i++)        {        glBegin(GL_QUADS);                //Red        glColor3f(1,0,0);          glVertex3f(1, 1,zPos);                //Yellow        glColor3f(1,1,0);          glVertex3f(1,-1,zPos);                //Green        glColor3f(0,1,0);          glVertex3f(-1,-1,zPos);                //Blue        glColor3f(0,0,1);          glVertex3f(-1,1,zPos);         glEnd();                  glTranslatef(2,0,0.1);        }}

This is my source atm and I get nothing on the screen. The set OGL_2D() was copied from Last post about 2D in OpenGL (so please stop!).

So what am I doing wrong here?

##### Share on other sites
My guess? The very typical and usual mistake of doing

glOrtho(0, vPort[2], 0, vPort[3], -100, 100);
glOrtho(0, vPort[2], vPort[3], 0, -100, 100);

hence everything is flipped upside down, hence an inverted winding order on your primitives and hence they are all backface culled (can you tell I like chicken?).

Also, if your viewport is ranging from 0-x then using negative coordinates doesn't make a lot of sense (unless you WANT them to be outside, of course). If you want the origin to be in the middle your glOrtho call should use +-vPort[x]/2

##### Share on other sites
I tried it :( and I still cant see anything

InitScene(){	glShadeModel(GL_SMOOTH);                // Enable smooth shading	glClearColor(0.0f, 0.0f, 0.0f, 0.5f);   // Black background	glClearDepth(1.0f);                     // Depth buffer setup	glEnable(GL_DEPTH_TEST);                // Enables depth testing	glDepthFunc(GL_LEQUAL);                 // The type of depth testing to do	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);      // Really nice perspective calculations		return true;}

My initialization code.... glClearDepth(1.0f) this causing the trouble?

If so what value should be passed to the function?

(Btw, the render function allows one to alter the z coordinates of 3 quads. So one can move them up and down along the z axis. This is just saying what the code is trying to do)

##### Share on other sites
You are using the viewport dimensions, probably the window size, for your orthographic projection. That makes each pixel on screen 1 unit2, making the quads you are rendering just a few pixels each. You are also drawing around the origin, which is in the lower left corner of the screen, so the parts of the quads with negative coordinates won't be on screen and you will only be rendering a pixel or two in the corner.

##### Share on other sites
Yee haaaaa,

I got something on my screen :).

void OGL_2D(){  int vPort[4];   glGetIntegerv(GL_VIEWPORT, vPort);   glMatrixMode(GL_PROJECTION);   glPushMatrix();   glLoadIdentity();   glOrtho(0, vPort[2], vPort[3], 0, -100, 100);   glMatrixMode(GL_MODELVIEW);   glPushMatrix();   glLoadIdentity();}void Render(){	static float zPos = 0;	if(KeyPress(VK_ESCAPE))FlagQuit();			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	glLoadIdentity();        glTranslatef(200,200,0);        if(KeyPress(VK_UP))++zPos;        else if(KeyPress(VK_DOWN))--zPos;                        glBegin(GL_QUADS);        glColor3f(1,0,1);          glVertex3i(0, 1,-10);          glVertex3i(0,-1,-10);          glVertex3i(-1,-1,-10);          glVertex3i(-1,1,-10);         glEnd();                        for(int i=0;i<3;i++)        {        glBegin(GL_QUADS);                //Red        glColor3f(100,0,0);          glVertex3f(100, 100,zPos);                //Yellow        glColor3f(100,100,0);          glVertex3f(100,-100,zPos);                //Green        glColor3f(0,1,0);          glVertex3f(-100,-100,zPos);                //Blue        glColor3f(0,0,1);          glVertex3f(-100,100,zPos);         glEnd();                  glTranslatef(200,0,10);        }}

Output:

The origin (0,0) is the top left of the screen.

Some info I found useful ;)
Quote:
 Source: MSDNglGetIntegerv(GL_VIEWPORT, ...)GL_VIEWPORT The params parameter returns four values: the x and y window coordinates of the viewport, followed by its width and height.glViewportThe glViewport function sets the viewport.void glViewport( GLint x, GLint y, GLsizei width, GLsizei height);Parametersx, y The lower-left corner of the viewport rectangle, in pixels. The default is (0,0).width, height The width and height, respectively, of the viewport. When an OpenGL context is first attached to a window, width and height are set to the dimensions of that window.

OpenGL Red Book
OpenGL FAQ
cprogramming.com: Projections in OpenGL
Hope someone with the same problem find these links as useful as I did

Thanks a lot all of you. You've been a great help.

##### Share on other sites
look at glRasterPos, it's not intuitive how to use it in perspective though.
Better is to switch to orthographic projection like people said.

## Create an account

Register a new account

• ## Partner Spotlight

• ### Forum Statistics

• Total Topics
627658
• Total Posts
2978474
• ### Similar Content

• Both functions are available since 3.0, and I'm currently using glMapBuffer(), which works fine.
But, I was wondering if anyone has experienced advantage in using glMapBufferRange(), which allows to specify the range of the mapped buffer. Could this be only a safety measure or does it improve performance?
Note: I'm not asking about glBufferSubData()/glBufferData. Those two are irrelevant in this case.
• By xhcao
Before using void glBindImageTexture(    GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format), does need to make sure that texture is completeness.
• By cebugdev
hi guys,
are there any books, link online or any other resources that discusses on how to build special effects such as magic, lightning, etc. in OpenGL? i mean, yeah most of them are using particles but im looking for resources specifically on how to manipulate the particles to look like an effect that can be use for games,. i did fire particle before, and I want to learn how to do the other 'magic' as well.
Like are there one book or link(cant find in google) that atleast featured how to make different particle effects in OpenGL (or DirectX)? If there is no one stop shop for it, maybe ill just look for some tips on how to make a particle engine that is flexible enough to enable me to design different effects/magic
let me know if you guys have recommendations.
• By dud3
How do we rotate the camera around x axis 360 degrees, without having the strange effect as in my video below?
Mine behaves exactly the same way spherical coordinates would, I'm using euler angles.
Tried googling, but couldn't find a proper answer, guessing I don't know what exactly to google for, googled 'rotate 360 around x axis', got no proper answers.

References:
Code: https://pastebin.com/Hcshj3FQ
The video shows the difference between blender and my rotation:

• By Defend
I've had a Google around for this but haven't yet found some solid advice. There is a lot of "it depends", but I'm not sure on what.
My question is what's a good rule of thumb to follow when it comes to creating/using VBOs & VAOs? As in, when should I use multiple or when should I not? My understanding so far is that if I need a new VBO, then I need a new VAO. So when it comes to rendering multiple objects I can either:
* make lots of VAO/VBO pairs and flip through them to render different objects, or
* make one big VBO and jump around its memory to render different objects.
I also understand that if I need to render objects with different vertex attributes, then a new VAO is necessary in this case.
If that "it depends" really is quite variable, what's best for a beginner with OpenGL, assuming that better approaches can be learnt later with better understanding?

• 10
• 12
• 22
• 13
• 33