2017-08-17 103 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