我正在尝试使用OpenGL(C ++)将两个纹理渲染到一个矩形上。我在混合他们两个时遇到了一些麻烦。
第一张图片来自.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时,我得到(如预期的那样)只有一个纹理。
答案 0 :(得分:3)
问题可能在于纹理本身。如果您探测在边界附近被alpha取消的像素处的半透明纹理,那么RGB值是多少?一些编辑器(深刻地用Photoshop)用透明区域填充白色(或默认颜色),这可能会在混合过程中导致这些边框。
Antialising或插值会导致白色进入可见区域。
我从软件开发人员的角度来看并没有解决这个问题,但是作为内容创建者(例如,它在SecondLife中是新手的祸害)不止一次地将其解决了。
答案 1 :(得分:0)
这解决了我的问题:
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);