problem blending properly in openGL - c++

I'm trying to draw a 2d character sprite on top of a 2d tilemap, but when I draw the character he's got odd stuff behind him. This isn't in the sprite, so I think its the blending.
This is how my openGL is set up:
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glViewport(0, 0, Width, Height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glDisable(GL_DEPTH_TEST); // Enables Depth Testing
//glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
glShadeModel(GL_FLAT);
glMatrixMode(GL_PROJECTION);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glAlphaFunc(GL_GREATER, 0.5f);
glMatrixMode(GL_PROJECTION);//configuring projection matrix now
glLoadIdentity();//reset matrix
glOrtho(0, Width, 0, Height, 0.0f, 100.0f);//set a 2d projection matrix
}
How should I set this up to work properly (i.e. drawing the sprite without odd stuff behind him.
This is what I am talking about: http://i.stack.imgur.com/cmotJ.png
PS: I need to be able to put transparent/semi-transparent images on top of each other and have whats behind them visible too

Does your sprite have premultiplied alpha? Your glBlendFunc setup is a little unusual, if you don't have premultiplied alpha it could definitely be causing the issue.

Related

Texture not appearing on the screen Opengl

I want to load an image on the background, I have written following code to load the texture as background by texturing the Rectangle. My image is in power of 2 (512x512). I am not getting why it is not showing anything on the screen,
please help me in this.
I am pasting my code to load the texture and to draw the rect.
Also, I have checked whether the image is loaded properly or not by using SOIL_last_result() and also checked whether there is any error in OpenGL by using glGetError()
Code to load the image as a texture using SOIL
void loadTexture(GLuint* texture, char* path){
*texture = SOIL_load_OGL_texture(path,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
SOIL_FLAG_NTSC_SAFE_RGB | SOIL_FLAG_MULTIPLY_ALPHA
);
cout<<*texture<<endl;
if(*texture == NULL){
printf("Failed to load %s", path);
}
}
Following code is to draw texture and rectangle,
void drawRect(int x, int y, int w, int h, GLuint texture){
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
glColor3f(1.0,1.0,1.0);
glBegin(GL_POLYGON);
glTexCoord2i(0,0);
glVertex2i(x,y);
glTexCoord2i(1,0);
glVertex2i(x+w,y);
glTexCoord2i(0,1);
glVertex2i(x,y+h);
glTexCoord2i(1,1);
glVertex2i(x+w,y+h);
glEnd();
glPopMatrix();
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
}
And I am calling it using init mehod,
void initGL(void)
{
glClearDepth(1.0);
glClearColor(0,0,0, 1.0f);
glColor3f(0.0, 0.0, 0.0);
glLineWidth(1);
glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
GLuint texture;
loadTexture(&texture, "image.png");
drawRect(0,0,screen_width-100,screen_height-100,texture);
glfwSwapBuffers(window);
}
Please help me and let me know if you need more information.
Thanks in advance!!
The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. It transforms from eye space to the clip space, and the coordinates in the clip space are transformed to the normalized device coordinates (NDC) by dividing with the w component of the clip coordinates. The NDC are in range (-1,-1,-1) to (1,1,1). Every geometry which is out of the clippspace is clipped.
Since you do not set up a projection matrix, you're projection matrix is the identity matrix. This means you will only "see" the geometry, whose coordinates are in the range -1 to 1.
I recommend to setup a orthographic projection matrix (glOrtho). At Orthographic Projection the coordinates in the eye space are linearly mapped to normalized device coordinates and the clip sapce coordinates are equal the normalized device coordiantes.
Set up the projection somehow like this:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, screen_width, 0, screen_height, -1, 1);

OpenGL fill frustum with quad

I'm trying to write an OpenGL/GLSL app that will use GLSL for image processing. I've done some research and come to the conclusion that the right approach is to render to a framebuffer object and then retrieve the image from the gpu. Unfortunately I can't figure out how to set up the frustum and render the quadrilateral so that it fills it properly. Does anyone know how to do this?
You need to render with an orthogonal projection matrix.
glPushMatrix(GL_WORLDVIEW);
glLoadIdentity();
glPushMatrix(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 0, 1);
glBegin(GL_QUADS);
glVertex2i(0, 0);
glVertex2i(width, 0);
glVertex2i(width, height);
glVertex2i(0, height);
glEnd();
glPopMatrix();
glMatrixMode(GL_WORLDVIEW);
glPopMatrix();
Width and height are the dimensions of your FBO. Of course they could be both one if you don't need to address special parts of your FBO by drawing quads at pixel positions.

How to set pixel coordinates?

Is it possible to draw something in OpenGL on the drawing scene with giving window pixel coordinates?
For example, I'd like to draw a single point in a 400x400 window (e.g. in the middle of that window). Is there any quick way to set everything up so I could just type:
glVertex3f(200.0 , 200.0 , 1.0);?
You need to set up an orthogonal projection matrix for that first.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(0.0f, WindowWidth, WindowHeight, 0.0f, 0.0f, 10.0f);
glMatrixMode(GL_MODELVIEW);
You can then render in window coordinates.
glPointSize(5.0f);
glBegin(GL_POINTS);
glVertex3f(100.0f, 100.0f, 1.0f);
glEnd();
Should render a point with a diameter of 5 pixels on window coordinates [100, 100]
Do note that this old way of rendering is deprecated and you should use VBOs and the like, but it is still good for testing.

3d cube opengl - overlapping sides

I want to create a 3d cube with openGL. Also, I want to cover each side with an image that I transform in a texture.
I find cube coordinates in 2D, and I create a QUADS for each side.
My problem is that when I render textures corresponding cube sides, I see these textures overlap each other, as you can see in this image:
my code is:
Initialization:
glGenTextures(2, textures);
glClearColor (0.0, 0.0, 0.0, 0.0);
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_ALWAYS);
Transform image in thexture:
up = imread("up.png");
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, up.cols, up.rows, GL_RGB, GL_UNSIGNED_BYTE, up.data);
Display cube:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
// Set Projection Matrix
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, WIDTH, HEIGHT, 0);
// Switch to Model View Matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, textures[1]);
glBegin(GL_QUADS);
//sopra
glTexCoord2f(0.0f, 0.0f); glVertex2f((GLfloat)((coord[6].x)),(GLfloat)(coord[6].y));
glTexCoord2f(1.0f, 0.0f); glVertex2f((GLfloat)((coord[5].x)),(GLfloat)(coord[5].y));
glTexCoord2f(1.0f, 1.0f); glVertex2f((GLfloat)((coord[4].x)),(GLfloat)(coord[4].y));
glTexCoord2f(0.0f, 1.0f); glVertex2f((GLfloat)((coord[7].x)),(GLfloat)(coord[7].y));
glEnd();
I do the same for the other sides of the cube.
The order in which I render textures is:
bottom (ground) side
up side
behind side
front side
left side
right side
what is wrong or what am I missing? Or, Maybe cannot create a 3d cube with 2d coordinates (glVertex2f (...))?
Thanks for your help!
You can't create a cube with 2d coordinates. The sides are overlapping because they are all on the same plane in space. A cube is in 3d space so needs 3 coordinates, x, y, and z.
So try using:
glVertex3f(x, y, z);
and use some appropriate z values depending on where you want each face.
For the texture you can still use:
glTexCoord2f(x, y);
since the textures are in 2 dimensional space.
If you are still confused about what to use for your coordinates I suggest you read this to help you understand 3d space in openGL:
http://www.falloutsoftware.com/tutorials/gl/gl0.htm

Draw polygons above background image

My question is to draw a polygon or some other OpenGL primitives above or over a background image. Summarizing like paint in different layers, but in OpenGL i think there is no layers.
Now i'm doing some test trying to draw a triangle and a line over the background image.
To draw the background i use a square with OpenGL window size and then apply the png image in this square as a texture.
After that I try to paint the triangle and the line with different colors but I don't see anything except the background image.
I play with the alpha channel but i don't see anything.
Code:
void init()
{
// glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
// The following two lines enable semi transparent
glEnable(GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int width, height;
bool hasAlpha;
char filename[] = "prueba-luz.png";
bool success = loadPngImage(filename, width, height, hasAlpha, &textureImage);
if (!success)
{
cout << "Unable to load png file" << endl;
return;
}
cout << "Image loaded " << width << " " << height << " alpha " << hasAlpha << endl;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, hasAlpha ? 4 : 3, width,
height, 0, hasAlpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE,
textureImage);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
void display(void)
{
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Igual que GL_REPLACE pero se le puede aplicar transparencias a la textura
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glColor4f(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glTexCoord2i(0,0); glVertex2i(10, -10);
glTexCoord2i(1,0); glVertex2i(-10, -10);
glTexCoord2i(1,1); glVertex2i(-10, 10);
glTexCoord2i(0,1); glVertex2i(10, 10);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glBegin(GL_POLYGON);
glColor4f(1.0, 1.0, 1.0, 0.8);
glVertex3f(-1.0f, -3.0f, 0.0f); // A
glVertex3f( 1.0f, -3.5f, 0.0f); // B
glVertex3f( 0.0f, 0.5f, 0.0f); // C
glEnd();
glBegin(GL_LINES);
glColor4f( 1.0, 0.0, 0.0, 0.8 );
glVertex2f(-8.0, 6.0);
glVertex2f (5.0, -3.0);
glEnd();
glutSwapBuffers();
}
How can i draw one image over the background image ???
Some things spotted :
Try to disable depth test. You are drawing everything at Z=0 and your application is definitely writing to the depth buffer. I'm not sure why you enable depth testing here since everything you draw is on Z=0.
By default all fragments written to the same or higher Z value will be discarded when depth testing is enabled. This can be changed with glDepthFunc (Default value GL_LESS). This is probably why your geometry is discarded in this example.
Drawing 2D geometry do not mean that the depth buffer will not be affected. OpenGL will draw this geometry with Z=0 and write that to your depth buffer.
Currently there is no reason for your application to use depth testing unless you draw your geometry on different z positions. You can use depth testing in 2D drawing to make "layers" by assigning different z values to each object.
A good practice for 2D drawing with z-culling is to draw the closes layer first, then draw the layers further in. This makes sure your write fewer fragments.
For example :
Z = 0 : Draw non-transparent overlays
Z = -1 : Draw stuff hidden behind the overlays
Z = -2 : Draw background
However, transparent objects need special rules.
You need to get control over your depth buffer. There are options :
glEnable/Disable(GL_DEPTH_TEST) : Enable or disable z-culling
glDepthMask(GL_TRUE/GL_FALSE) : Enable or disable writing to the the depth buffer
(glDepthFunc can be used to define how fragments are discarded)
Note here that the two first functions give you way more options than you might think
Depth culling and depth write when drawing objects
Depth culling, but your object do not affect the depth buffer
No depth culling, but your object will write to the depth buffer
No depth culling and no depth write
If you want to draw all your transparent objects in a last pass you can for example enable depth testing so the objects are not drawn on top your your overlays, but you disable depth writes because you want to be able to draw several overlapping objects in that layer.
Use your creativity and learn to love the depth buffer :D