我注意到我的openGL纹理渲染中存在一个大问题:
假设透明像素呈现为纯白色。根据StackOverflow上讨论的类似问题的大多数解决方案,我需要设置glBlend /正确的函数,但我已经设置了必要的gl状态,并且我认为纹理正确加载是正确的。我的纹理加载函数如下:
GLboolean GL_texture_load(Texture* texture_id, const char* const path, const GLboolean alpha, const GLint param_edge_x, const GLint param_edge_y)
{
// load image
SDL_Surface* img = nullptr;
if (!(img = IMG_Load(path))) {
fprintf(stderr, "SDL_image could not be loaded %s, SDL_image Error: %s\n",
path, IMG_GetError());
return GL_FALSE;
}
glBindTexture(GL_TEXTURE_2D, *texture_id);
// image assignment
GLuint format = (alpha) ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, format, img->w, img->h, 0, format, GL_UNSIGNED_BYTE, img->pixels);
// wrapping behavior
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, param_edge_x);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, param_edge_y);
// texture filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
// free the surface
SDL_FreeSurface(img);
return GL_TRUE;
}
我使用Adobe Photoshop导出“for the web”24位+透明度.png文件 - 72像素/英寸,6400 x 720.我不知道如何设置颜色模式(8,16,32) ,但这可能与问题有关。我也使用默认的sRGB颜色配置文件,但我想在一个点上删除颜色配置文件。这没有做任何事情。 无论如何,从Photoshop导出的png在透明像素上显示为纯白色。
如果我在例如Gimp,我有正确的透明度。导入Adobe .psd或.png似乎不起作用,无论如何我更喜欢使用Photoshop进行编辑。
有没有人遇到过这个问题?我想Photoshop必须添加一些奇怪的元数据,或者我没有使用正确的颜色模式 - 或两者兼而有之。 (我担心这超出了Stack Overflow的范围,但我的问题与图像编辑和编程相交。无论如何,如果这不是正确的地方,请告诉我。)
编辑:
在Photoshop和Gimp中,我创建了一个测试用例 - 顺时针方向为8像素(红色,绿色,透明,蓝色)。
在Photoshop中,透明正方形读取为1,1,1,0并显示为白色。 在Gimp中,透明正方形是0,0,0,0。
我还检查了片段着色器,看透明度是否有效。随着时间的推移改变alpha会增加透明度,因此alpha不会被完全忽略。出于某种原因,1,1,1,0计为固体。 此外,使用glClearColor将背景颜色设置为黑色似乎可以防止alpha增加透明度。
我不知道如何解释这些行为中的一些,但似乎有些东西似乎没有。无论颜色如何,0 alpha应该是相同的,不应该吗?
(请注意,我在彼此的顶部渲染了一些形状,但我尝试只渲染一个用于测试目的。)
我能做的最好的事情是发布更多我的设置代码(省略位):
//顶点数组和缓冲区设置
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
// I think that the blend function may be wrong (GL_ONE that is).
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glDepthRange(0, 1);
glDepthFunc(GL_LEQUAL);
Texture tex0;
// same function as above, but generates one texture id for me
if (GL_texture_gen_and_load_1(&tex0, "./textures/sq2.png", GL_TRUE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE) == GL_FALSE) {
return EXIT_FAILURE;
}
glUseProgram(shader_2d);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex0);
glUniform1i(glGetUniformLocation(shader_2d, "tex0"), 0);
bool active = true;
while (active) {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// uniforms, game logic, etc.
glDrawElements(GL_TRIANGLES, tri_data.i_count, GL_UNSIGNED_INT, (void*)0);
}
答案 0 :(得分:2)
我不知道如何解释其中的一些行为,但似乎有些事情没有。无论颜色如何,0 alpha应该是相同的,不应该吗?
如果想要获得0.0的alpha通道的相同结果,独立于红色,绿色和蓝色通道,则必须更改混合功能。请参阅glBlendFunc
。
使用:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
这导致红色,绿色和蓝色通道乘以alpha通道。 如果alpha通道为0.0,则生成的RGB颜色为(0,0,0)。 如果alpha通道为1.0,则RGB颜色通道保持不变。
请参阅Alpha Compositing, OpenGL Blending and Premultiplied Alpha