problem rendering rect and 2d texture at same time OpenGL

Started by
2 comments, last by erpeo93 7 years, 11 months ago

Hello.

I am porting my game to android using SDL and NDK, and I am trying to make the game hardware accelerated with openGL.

In the game I need to draw colored rectangles and to draw an arbitrary bitmap.


void DrawRectangleGL( ScreenBuffer* buffer, Vec2 min, Vec2 max, Vec4 color )
{
GLfloat matrix[] = {
2.0f / buffer->width,  0,  0, 0,
0, 2.0f / buffer->height,  0, 0,
0, 0,                      1, 0,
  -1, -1,                     0, 1
};
 
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
glLoadIdentity();
glMultMatrixf( matrix );
 
GLfloat triangles[] = {
        min.X, min.Y,
        max.X, min.Y, 
        max.X, max.Y,
 
min.X, min.Y,
min.X, max.Y,
max.X, max.Y
    };
 
GLfloat colors[] = {
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W,
 
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W
};
 
    glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, triangles);
 
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, colors );
 
    glDrawArrays(GL_TRIANGLES, 0, 6);
}
The function is written correctly and it works: I can render colored rectangles everywhere I want. (you can see the result in onlyRect.png)
Also, if I try to render ONLY 2d texture I get them on the screen perfectly with this function: (you can see the result in onlyTexture.png)


void DrawBitmap( ScreenBuffer* buffer, Bitmap* bitmap, Vec2 position, real32 alpha )
{
if( bitmap->textureMap == -1 )
{
glGenTextures(1, ( GLuint* ) &bitmap->textureMap);
}
 
glBindTexture(GL_TEXTURE_2D, bitmap->textureMap );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bitmap->width, bitmap->height,
0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bitmap->pixels );
 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
 
glEnable( GL_TEXTURE_2D );
 
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
 
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
 
glMatrixMode( GL_PROJECTION );
glLoadIdentity(); 
 
GLfloat matrix[] = {
2.0f / buffer->width,  0,  0, 0,
0, 2.0f / buffer->height,  0, 0,
0, 0,                      1, 0,
  -1, -1,                     0, 1
};
 
glLoadIdentity();
glMultMatrixf( matrix );
 
 
Vec2 min = position;
Vec2 max = min + V2( bitmap->width, bitmap->height );
GLfloat triangles[] = {
        min.X, min.Y,
        max.X, min.Y, 
        max.X, max.Y,
 
min.X, min.Y,
        min.X, max.Y, 
        max.X, max.Y,
};
 
GLfloat textureVertices[] = {
        0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
 
        0.0f,  0.0f,
0.0f, 1.0f,
1.0f, 1.0f
};
 
    glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, triangles);
 
glEnableClientState( GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer( 2, GL_FLOAT, 0, textureVertices );
    glDrawArrays(GL_TRIANGLES, 0, 6);
}

The problem is that when I try render both rectangles and 2d texture at the same time, I get a very weird result, that you can see in both.png.
I've tried a couple of hours to solve the problem, without success.
Surely I am missing something stupid because it's the first time I use openGL, but searching into the web I did not find anything.
The problem Is just about the colors, because as you can see from both.png the position of the rect and the texture remains correct.
ps: I am clearing the screen to black and setting the viewport at the beginning of every frame with


glViewport(0, 0, globalScreenBuffer.width, globalScreenBuffer.height );
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

There is no other OpenGL code in the program, other than the initialization code obviously.
Thank you in advance.
Leonardo
Advertisement

Two things that directly stand out to me are the matrix and the vertex states.


The matrix that is active at start by default is GL_MODELVIEW. So if you only call the first function, that matrix will be modified by

glLoadIdentity();
glMultMatrixf( matrix );

But the second function sets GL_PROJECTION active before it returns. So if you then call the first function again, you now modify that one. And even if you activate the GL_MODELVIEW here, the GL_PROJECTION would still hold the old value from the second function.


You also enable different VERTEX types with glEnableClientState, but never disable them.


Remember that lots of OpenGL states are global states in the current OpenGL context.
The easy way is just to disable them/set the standard value directly after use. This is not the most performance way to use OpenGL, but for a small project that should not be an issue.

Two things that directly stand out to me are the matrix and the vertex states.


The matrix that is active at start by default is GL_MODELVIEW. So if you only call the first function, that matrix will be modified by


glLoadIdentity();
glMultMatrixf( matrix );
But the second function sets GL_PROJECTION active before it returns. So if you then call the first function again, you now modify that one. And even if you activate the GL_MODELVIEW here, the GL_PROJECTION would still hold the old value from the second function.


You also enable different VERTEX types with glEnableClientState, but never disable them.


Remember that lots of OpenGL states are global states in the current OpenGL context.
The easy way is just to disable them/set the standard value directly after use. This is not the most performance way to use OpenGL, but for a small project that should not be an issue.

thank you for the quick reply.

I've changed some of the code, and it is getting better: as you said I was never calling glDisableClientState, and that was a problem.

Now I have another problem: the position of both the texture and rectangle is correct, even when they are rendered togheter, but seems to me like only the alpha channel of the Rect is drawed, while the red green and blue don't exist. On the other side, texture are rendered perfectly in any situation.

Rect rendering:


void DrawRectangleGL( ScreenBuffer* buffer, Vec2 min, Vec2 max, Vec4 color )
GLfloat matrix[] = {
2.0f / buffer->width,  0,  0, 0,
0, 2.0f / buffer->height,  0, 0,
0, 0,                      1, 0,
  -1, -1,                     0, 1
};
 
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
 
glMultMatrixf( matrix );
 
GLfloat triangles[] = {
        min.X, min.Y,
        max.X, min.Y, 
        max.X, max.Y,
 
min.X, min.Y,
min.X, max.Y,
max.X, max.Y
    };
 
GLfloat colors[] = {
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W,
 
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W,
color.X, color.Y, color.Z, color.W
};
 
    glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, triangles);
 
glEnableClientState( GL_COLOR_ARRAY );
glColorPointer( 4, GL_FLOAT, 0, colors );
 
    glDrawArrays(GL_TRIANGLES, 0, 6);
 
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_VERTEX_ARRAY );
glDisable( GL_BLEND );

Bitmap rendering:


 
void DrawBitmap( ScreenBuffer* buffer, Bitmap* bitmap, Rect destRect, real32 alpha, Rect clip = { 0, 0, 1, 1} )
{
if( bitmap->textureMap == -1 )
{
glGenTextures(1, ( GLuint* ) &bitmap->textureMap);
}
 
glBindTexture(GL_TEXTURE_2D, bitmap->textureMap );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bitmap->width, bitmap->height,
0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bitmap->pixels );
 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
 
glEnable( GL_TEXTURE_2D );
 
glEnable (GL_BLEND);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
glMatrixMode( GL_TEXTURE );
glLoadIdentity();
 
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
 
GLfloat matrix[] = {
2.0f / buffer->width,  0,  0, 0,
0, 2.0f / buffer->height,  0, 0,
0, 0,                      1, 0,
  -1, -1,                     0, 1
};
glMultMatrixf( matrix );
 
glMatrixMode( GL_PROJECTION );
glLoadIdentity(); 
 
 
Vec2 min = destRect.minCorner;
Vec2 max = destRect.maxCorner;
GLfloat triangles[] = {
        min.X, min.Y,
        max.X, min.Y, 
        max.X, max.Y,
 
min.X, min.Y,
        min.X, max.Y, 
        max.X, max.Y,
};
 
GLfloat textureVertices[] = {
        clip.minCorner.X, clip.minCorner.Y,
clip.maxCorner.X, clip.minCorner.Y,
clip.maxCorner.X, clip.maxCorner.Y,
 
clip.minCorner.X, clip.minCorner.Y,
clip.minCorner.X, clip.maxCorner.Y,
clip.maxCorner.X, clip.maxCorner.Y, 
};
 
    glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, triangles);
 
glEnableClientState( GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer( 2, GL_FLOAT, 0, textureVertices );
    glDrawArrays(GL_TRIANGLES, 0, 6);
 
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
 
glPopMatrix();

again, probably I am missing something about the matrices stack, and how it works, bacause as you can see from the image if I draw just rect they are rendered perfectly.

Note: I am drawing a rect as background, that's the reason why in rect.png there is a gray background.

Again, sorry for the ridicoulus questions, the fact is that now the position is correct and the texture are rendered in the right way, just the rects colors are wrong.

Leonardo

Resolved.

I was not calling glDisable(GL_TEXTURE_2D).

This topic is closed to new replies.

Advertisement