OpenGL blending creates white border around textures
Asked Answered
A

2

9

I'm trying to use OpenGL (C++) to render two textures onto a rectangle. I'm having some trouble blending the two of them though.

The first image comes from a .jpg file (https://learnopengl.com/img/textures/container.jpg). This image has no alpha channel.

The second image comes from a .png file (https://learnopengl.com/img/textures/awesomeface.png) and does have an alpha channel.

The problem is when I try to blend the two images, it creates a white border around the transparent image.

I've tried a few different blending modes (as recommended by the OP in this question: Alpha blending with multiple textures leaves colored border) but none of them seem to work.

My fragment shader looks like this:

#version 330 core
out vec4 FragColor;

in vec3 ourColor;
in vec2 TexCoord;

// texture samplers
uniform sampler2D texture1;
uniform sampler2D texture2;

void main()
{
    // linearly interpolate between both textures
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.5);
}

I have depth testing enabled (doesn't seem to have any effect) and I'm using the following code for setting up my blending:

glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

This is my main render loop:

Rendering::Pipeline pipeline = Rendering::Pipeline("src/GLSL/vertex.glsl", "src/GLSL/fragment.glsl");
pipeline.load();

//                     Position,               Color,                   Texture Coord.
//                     (X Y Z)                 (R G B)                  (S T)
float vertices [32] = { 0.5f,   0.5f,   0.0f,   1.0f,   0.0f,   0.0f,   1.0f, 1.0f, // top right
                        0.5f,   -0.5f,  0.0f,   0.0f,   1.0f,   0.0f,   1.0f, 0.0f, // bottom right
                        -0.5f,  -0.5f,  0.0f,   0.0f,   0.0f,   1.0f,   0.0f, 0.0f, // bottom left
                        -0.5f,  0.5f,   0.0f,   1.0f,   1.0f,   0.0f,   0.0f, 1.0f  };// top left

unsigned int vertexIndices [6] = {  3,  2,  0,
                                    2,  1,  0   };


unsigned int vbo;
unsigned int vao;
unsigned int ebo;

glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);

glBindVertexArray(vao);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexIndices), vertexIndices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) 0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) (3 * sizeof(float)));
glEnableVertexAttribArray(1);

glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) (6 * sizeof(float)));
glEnableVertexAttribArray(2);

unsigned int texture1;
unsigned int texture2;
int width;
int height;
int numChannels;
unsigned char* data;

glGenTextures(1, &texture1);
glBindTexture(GL_TEXTURE_2D, texture1);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

data = stbi_load("res/jpg/container.jpg", &width, &height, &numChannels, STBI_rgb);

if (data)
{
    lTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}

stbi_image_free(data);

glGenTextures(1, &texture2);
glBindTexture(GL_TEXTURE_2D, texture2);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

stbi_set_flip_vertically_on_load(true);

data = stbi_load("res/png/awesomeface.png", &width, &height, &numChannels, STBI_rgb_alpha);

if (data)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}

stbi_image_free(data);

glUseProgram(pipeline.getProgramId());
glUniform1i(glGetUniformLocation(pipeline.getProgramId(), "texture1"), 0);
glUniform1i(glGetUniformLocation(pipeline.getProgramId(), "texture2"), 1);

while (!this->mQuit)
{
    this->counter.start();

    InputProcessor::getInstance().processInputs();

    if (this->debugOverlay)
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    }
    else
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture1);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture2);

    pipeline.use();
    glBindVertexArray(vao);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    SDL_GL_SwapWindow(this->sdlWindow);

    this->counter.stop();
    this->deltaTime = this->counter.getDelta();
}

    this->quit();

The issue is most easily observed when passing 0.5 as parameter to the mix() function in the fragment shader. When using 0.0 or 1.0 I get (as expected) only one of the textures.

Arrivederci answered 17/8, 2017 at 18:44 Comment(0)
P
5

The problem might be with texture itself. if you probe the semitransparent texture at pixel that got cancelled by alpha near border, what RGB values are? Some editors (Photoshop profoundly) fill the transparent area with white color (or with default color) , which may cause those border during blending.

Antialising or interpolation would cause that white to creep into visible area.

I dealt not with this problem from software developer point of view, but had been ground by it more than once as content creator (it's a novice's scourge in SecondLife, for example).

Plaint answered 17/8, 2017 at 18:51 Comment(1)
Thank you very much! This was the solution, I opened my transparent texture up in GIMP and exported it, making sure to not tick "Save background colour", after this, the texture blended as it should!Arrivederci
P
4

This fixed the issue for me:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

Pazit answered 5/4, 2018 at 6:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.