Reputation: 1172
What can I try to solve this problem? In this example (see a screenshot below) I am using OpenGL 1.1 with deprecated functions like: glEnableClientState, glMatrixMode, glTexCoordPointer, and so on. Thanks in advance.
You can see the whole example code in this thread: https://community.khronos.org/t/window-background-visible-through-textures/109061
I draw with DEPTH_TEST
:
glEnable(GL_DEPTH_TEST);
/* ... */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Player
glBindTexture(GL_TEXTURE_2D, spriteTexture);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(playerBody->GetPosition().x * WORLD_SCALE,
playerBody->GetPosition().y * WORLD_SCALE, 10.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, drawingIndex, 4);
// Coin
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(178.f, 120.f, 10.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 24, 4);
// Enemy
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(194.f, 184.f, 10.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
// Background
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.f, 0.f, 0.f);
glScalef(256.f, 216.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glfwSwapBuffers(window);
Texture:
Various window background values to show that I have an alpha channel:
For glClearColor(1.f, 0.f, 0.f, 1.f);
For glClearColor(0.2f, 0.5f, 0.3f, 1.f);
My Settings:
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
GLuint createTexture(char *path)
{
int h_image, w_image, cnt;
unsigned char *data = stbi_load(path, &w_image, &h_image, &cnt, 0);
if (data == NULL)
{
cout << "Failed to load an image" << endl;
glfwTerminate();
exit(-1);
}
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w_image, h_image, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(data);
return texture;
}
Upvotes: 6
Views: 161
Reputation: 211230
Transparency is achieved with the alpha channel and Blending only works when the textures have an alpha channel. When the alpha channel of the transparent background is 0.0 and the alpha channel of the object is 1.0 then you can use the following blending function:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
How can the objects be blended with the background if there is no background? You have to draw the background before you draw the objects and you don't nee the depth test at all. You must draw the object after the background. Using the depth test, fragments are discarded before they can be blended. You have to disable the depth test and draw the objects backt to front.
To render the scene you have to
disable blending and disable the depth test
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
draw the background
enable blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
draw the objects in the scene
Upvotes: 7
Reputation: 1172
you don't nee the depth test at all
Yes, I removed the depth test and it still works without it. And it's better because I don't have to think about the z-axis for all sprites. I can just set the Z position for all objects to 0.
Just additional information to Rabbid76's solution about the depth test. Not only the drawing order plays a role, but also the location along the z-axis. For example, this is the correct location on the z-axis: z = 0 for background, z = 5 for coin, z = 10 for enemy and z = 15 for player:
// Background
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.f, 0.f, 0.f);
glScalef(256.f, 216.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, spriteTexture);
// Coin
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(178.f, 120.f, 5.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 24, 4);
// Enemy
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(194.f, 184.f, 10.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
// Player
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(playerBody->GetPosition().x * WORLD_SCALE,
playerBody->GetPosition().y * WORLD_SCALE, 15.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, drawingIndex, 4);
glfwSwapBuffers(window);
Wrong order on z-axis, for example: z = 15 for coin, z = 10 for enemy and z = 5 for player:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Background
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.f, 0.f, 0.f);
glScalef(256.f, 216.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 16, 4);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glBindTexture(GL_TEXTURE_2D, spriteTexture);
// Coin
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(178.f, 120.f, 15.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 24, 4);
// Enemy
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(194.f, 184.f, 10.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, 20, 4);
// Player
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(playerBody->GetPosition().x * WORLD_SCALE,
playerBody->GetPosition().y * WORLD_SCALE, 5.f);
glScalef(16.f, 16.f, 1.f);
glDrawArrays(GL_TRIANGLE_STRIP, drawingIndex, 4);
glfwSwapBuffers(window);
Upvotes: 1