2017-08-17 81 views
5

我想使用OpenGL(C++)将两个纹理渲染到矩形上。尽管如此,我仍然遇到了一些麻烦。OpenGL混合创建纹理周围的白色边框

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

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

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

我已经尝试了几种不同的混合模式(如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时,我得到(如预期的)只有一个纹理。

回答

3

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

抗静电或插值会导致白色蠕变到可见区域。

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

+1

非常感谢!这是解决方案,我在GIMP中打开透明纹理并导出它,确保不勾选“保存背景颜色”,之后,纹理就会混合在一起! – shmoo6000