Blending OpenGL creates a white border around textures

I am trying to use OpenGL (C ++) to render two textures into a rectangle. I have problems mixing two of them.

The first image comes from a .jpg file ( https://learnopengl.com/img/textures/container.jpg ). This image does not have an alpha channel.

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

The problem is that when I try to mix two images, it creates a white frame around the transparent image.

I tried several different blending modes (as the OP recommended in this question: Alpha blending with multiple textures leaves a colored frame ), 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 (it seems to have no effect) and I use the following code to set up my mix:

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

This is my main rendering cycle:

 Rendering::Pipeline pipeline = Rendering::Pipeline("src/GLSL/vertex.glsl", "src/GLSL/fragment.glsl"); pipeline.load(); // Position, Color, Texture Coord. // (XYZ) (RGB) (ST) 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 problem is most easily observed when passing 0.5 as a 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.

+5
source share
2 answers

The problem may be the texture itself. if you examine a translucent texture in a pixel that has been canceled by an alpha border, what are the RGB values? Some editors (Photoshop deep) fill the transparent area with white (or the default color), which may cause this border to be mixed.

Smoothing or interpolating will cause the white to creep into the visible area.

I did not consider this problem from the point of view of a software developer, but repeatedly treated it as a content creator (for example, this is new to SecondLife).

+3
source

This fixed the problem for me:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

0
source

Source: https://habr.com/ru/post/1270975/


All Articles