c++ - OpenGL 混合在纹理周围创建白色边框

标签 c++ opengl textures alpha alphablending

我正在尝试使用 OpenGL (C++) 将两个纹理渲染到一个矩形上。不过,我在混合这两者时遇到了一些麻烦。

第一张图片来自 .jpg 文件 ( https://learnopengl.com/img/textures/container.jpg )。 此图像没有 alpha channel 。

第二张图片来自 .png 文件 ( https://learnopengl.com/img/textures/awesomeface.png ),并且确实有一个 alpha channel 。

问题是当我尝试混合两个图像时,它会在透明图像周围创建一个白色边框。

我尝试了几种不同的混合模式(正如 OP 在这个问题中所推荐的:Alpha blending with multiple textures leaves colored border),但它们似乎都不起作用。

我的片段着色器看起来像这样:

#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);
}

我启用了深度测试(似乎没有任何效果)并且我正在使用以下代码来设置我的混合:

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

这是我的主要渲染循环:

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();

将 0.5 作为参数传递给片段着色器中的 mix() 函数时,最容易观察到该问题。当使用 0.0 或 1.0 时,我(如预期的那样)只得到一个纹理。

最佳答案

问题可能出在纹理本身。如果您探测被边界附近的 alpha 取消的像素处的半透明纹理,那么 RGB 值是多少?一些编辑器(Photoshop 深刻)用白色(或默认颜色)填充透明区域,这可能会导致在混合过程中出现这些边框。

抗锯齿或插值会导致白色蔓延到可见区域。

我不是从软件开发人员的角度处理这个问题,但作为内容创建者不止一次被它打倒(例如,在 SecondLife 中,这是新手的祸害)。

关于c++ - OpenGL 混合在纹理周围创建白色边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45742828/

相关文章:

c++ - GLfloats之间的比较

c++ - OpenGL 在纹理相交处失败

svg - 挤出具有多个孔的多个多边形并对组合形状进行纹理化

java - 可点击的纹理

c++ - 尝试索引头文件时 Eclipse CDT 崩溃

c++ - 通过指向数据成员的指针进行类成员访问是否被视为成员访问表达式?

java - LWJGL 渲染器需要 GLSL 和 OpenGL2

OpenGL ArcBall 旋转和动画使用插值?

c++ - 查找背包中带了哪些元素

c++ - C++ 中的继承和模板 : Why doesn't the following piece of code compile?