openGL прозрачные пиксели неожиданно белые

Я заметил большую проблему в рендеринге текстур 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 для экспорта «для Интернета» 24-битных + прозрачность .png файлов — 72 пикселя / дюйм, 6400 x 720. Я не уверен, как установить цветовой режим (8, 16, 32), но это может иметь какое-то отношение к проблеме. Я также использую цветовой профиль sRGB по умолчанию, но я решил удалить цветовой профиль в одной точке. Это ничего не сделало.
Независимо от того, что PNG, экспортированный из Photoshop, отображается в виде сплошного белого поверх прозрачных пикселей.

Если я создаю изображение, например, GIMP, у меня правильная прозрачность. Импорт Adobe .psd или .png, похоже, не работает, и в любом случае я предпочитаю использовать Photoshop для редактирования.

Кто-нибудь сталкивался с этой проблемой? Я полагаю, что Photoshop должен добавить некоторые странные метаданные или я не использую правильные цветовые режимы — или оба.
(Я обеспокоен тем, что это выходит за рамки Stack Overflow, но моя проблема пересекается с редактированием изображений и программированием. В любом случае, пожалуйста, дайте мне знать, если это не то место.)

РЕДАКТИРОВАТЬ:

В Photoshop и Gimp я создал контрольный пример — 8 пикселей (красный, зеленый, прозрачный, синий) по часовой стрелке.

крошечный квадрат

В Photoshop прозрачный квадрат читается как 1, 1, 1, 0 и отображается белым.
В Gimp прозрачный квадрат равен 0, 0, 0, 0.

Я также проверил свой фрагментный шейдер, чтобы увидеть, работает ли прозрачность вообще. Изменение альфа-канала с течением времени увеличивает прозрачность, поэтому альфа не игнорируется. По какой-то причине 1, 1, 1, 0 считается сплошным.
Кроме того, установка цвета фона на черный с помощью glClearColor, по-видимому, препятствует увеличению прозрачности альфа-канала.

Я не знаю, как объяснить некоторые из этих поведений, но что-то не так. 0 альфа должна быть одинаковой независимо от цвета, не так ли?

(Обратите внимание, что я рендерил несколько фигур друг на друга, но я попробовал просто отрисовать одну для тестирования.)

Лучшее, что я могу сделать, это опубликовать больше моего установочного кода (с опущенными битами):

// массив вершин и настройка буферов

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);
}

1

Решение

Я не знаю, как объяснить некоторые из этих поведений, но что-то не так. 0 альфа должна быть одинаковой независимо от цвета, не так ли?

Если вы хотите получить идентичный результат для альфа-канала 0.0, независимо от красного, зеленого и синего каналов, вам нужно изменить функцию смешивания. Увидеть glBlendFunc.

Использование:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Это приводит к тому, что красный, зеленый и синий каналы умножаются на альфа-канал.
Если альфа-канал равен 0,0, результирующий цвет RGB равен (0, 0, 0).
Если альфа-канал равен 1,0, цветовые каналы RGB остаются неизменными.

Смотри дальше Альфа-композитинг, смешивание OpenGL и предварительное умножение альфа

2

Другие решения

Других решений пока нет …