Opengl: использовать текстуру одного канала в качестве альфа-канала для отображения текста - PullRequest
3 голосов
/ 24 марта 2012

Я пытаюсь загрузить текстуру в аппаратное обеспечение из одноканального массива данных и использовать его альфа-канал для рисования текста на объекте.Я использую opengl 4.

Если я пытаюсь сделать это, используя 4-канальную текстуру RGBA, она прекрасно работает, но по какой-то причине, когда я пытаюсь загрузить только один канал, я получаю искаженное изображение и могуне понимаю почему.Я создаю текстуру, комбинируя растровые данные текстуры для серии глифов со следующим кодом в одну текстуру:

int texture_height = max_height * new_font->num_glyphs;
int texture_width = max_width;

new_texture->datasize = texture_width * texture_height;
unsigned char* full_texture = new unsigned char[new_texture->datasize];

// prefill texture as transparent
for (unsigned int j = 0; j < new_texture->datasize; j++)
    full_texture[j] = 0;

for (unsigned int i = 0; i < glyph_textures.size(); i++) {
    // set height offset for glyph
    new_font->glyphs[i].height_offset = max_height * i;
    for (unsigned int j = 0; j < new_font->glyphs[i].height; j++) {
        int full_disp = (new_font->glyphs[i].height_offset + j) * texture_width;
        int bit_disp = j * new_font->glyphs[i].width;
        for (unsigned int k = 0; k < new_font->glyphs[i].width; k++) {
            full_texture[(full_disp + k)] =
                    glyph_textures[i][bit_disp + k];
        }
    }
}

Затем загружаю данные текстуры, вызывая:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->x, texture->y, 0, GL_RED, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(full_texture));

MyФрагмент шейдера выполняет следующий код:

#version 330

uniform sampler2D texture;

in vec2 texcoord;
in vec4 pass_colour;

out vec4 out_colour;

void main()
{
float temp = texture2D(texture, texcoord).r;
out_colour = vec4(pass_colour[0], pass_colour[1], pass_colour[2], temp);
}

Я получаю изображение, которое, как я могу сказать, генерируется из текстуры, но оно ужасно искажено, и я не уверен, почему.Кстати, я использую GL_RED, потому что GL_ALPHA был удален из Opengl 4. Что меня действительно смущает, так это то, почему это прекрасно работает, когда я генерирую текстуру 4 RGBA из символов и затем использую ее альфа-канал ??

Ответы [ 2 ]

15 голосов
/ 24 марта 2012
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->x, texture->y, 0, GL_RED, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(full_texture));

Это технически допустимо, но никогда хорошая идея.

Во-первых, вам необходимо понять, что является третьим параметром glTexImage2D.Это фактический формат изображения текстуры.Вы не создаете текстуру с одним каналом;вы создаете текстуру с четырьмя каналами.

Далее вам нужно понять, что делают последние три параметра.Это параметры передачи пикселей ;они описывают, как выглядят данные пикселей, которые вы передаете в OpenGL.

Эта команда говорит: «создайте 4-канальную текстуру, а затем загрузите некоторые данные в просто красный канал.данные хранятся в виде массива байтов без знака. "Загрузка данных только в некоторые каналов текстуры технически законна, но почти никогда не является хорошей идеей.Если вы создаете одноканальную текстуру, вы должны использовать одноканальную текстуру .А это означает правильный формат изображения.

Далее все становится более запутанным:

new_texture->datasize = texture_width * texture_height*4;

Использование «* 4» настоятельно рекомендует вам создавать четырехканальные пиксельные данные.Но вы загружаете только одноканальные данные.Остальные ваши вычисления согласны с этим;Вы, кажется, никогда не заполняете какой-либо проход данных full_texture[texture_width * texture_height].Таким образом, вы, вероятно, выделяете больше памяти, чем вам нужно.

И последнее: всегда используйте внутренние форматы размера.Никогда не используйте GL_RGBA;используйте GL_RGBA8 или GL_RGBA4 или что угодно.Не позволяйте водителю выбирать и надеяться, что он вам подойдет.

Итак, правильная загрузка будет такой:

glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, texture->x, texture->y, 0, GL_RED, GL_UNSIGNED_BYTE, full_texture);

К вашему сведению: reinterpret_cast не нужно;даже в C ++ указатели могут быть неявно преобразованы в void*.

3 голосов
/ 24 марта 2012

Я думаю, что вы поменяли местами параметры "внутреннего формата" и "формата" glTexImage2d ().То есть, вы сказали ему, что вы хотите RGBA в объекте текстуры, но имели только КРАСНЫЙ в данных файла, а не наоборот.

Попробуйте заменить ваш вызов следующим:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, texture->x, texture->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(full_texture));
...