代码之家  ›  专栏  ›  技术社区  ›  shmoo6000

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

  •  7
  • shmoo6000  · 技术社区  · 7 年前

    我正在尝试使用OpenGL(C++)将两个纹理渲染到一个矩形上。不过,我很难将两者融合在一起。

    第一个图像来自一个。jpg文件( https://learnopengl.com/img/textures/container.jpg 此图像没有alpha通道。

    第二个图像来自。png文件( https://learnopengl.com/img/textures/awesomeface.png )确实有一个alpha通道。

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

    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时,我(如预期)只得到一个纹理。

    2 回复  |  直到 7 年前
        1
  •  3
  •   Swift - Friday Pie    7 年前

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

    反序列化或插值会导致白色渗入可见区域。

        2
  •  3
  •   Paul    6 年前

    这为我解决了这个问题:

    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);