openGL прозрачные пиксели неожиданно белые - PullRequest
0 голосов
/ 09 мая 2018

Я заметил большую проблему в рендеринге текстур 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 должен добавить некоторые странные метаданные или я не использую правильные цветовые режимы - или оба. (Я обеспокоен тем, что это выходит за рамки переполнения стека, но моя проблема пересекается с редактированием изображений и программированием. В любом случае, пожалуйста, дайте мне знать, если это не то место.)

EDIT:

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

tiny square

В 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 голосов
/ 10 мая 2018

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

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

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

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

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


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

...