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.