Данные glTexImage2D заполнены не так, как ожидалось

#python #python-3.x #opengl #textures #pyopengl

#python #python-3.x #opengl #Текстуры #pyopengl

Вопрос:

Желая понять glTexImage2D, я написал следующий тестовый код на Python:

 import numpy as np
import OpenGL.GL as gl
import glfw

# initiating context
glfw.init()
w = glfw.create_window(100, 100, 'dd', None, None)
glfw.make_context_current(w)

# prepare sample image
width, height = 3, 3
image = np.array([i for i in range(width * height * 3)], dtype='ubyte')

# prepare texture
t = gl.glGenTextures(1)
gl.glBindTexture(gl.GL_TEXTURE_2D, t)

iformat = gl.GL_RGB
# upload texture
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, iformat, width, height, 0, iformat, gl.GL_UNSIGNED_BYTE, image)

# read texture
p = gl.glGetTexImage(gl.GL_TEXTURE_2D, 0, iformat, gl.GL_UNSIGNED_BYTE)

# display pixel values
pixels = iter(p)
for x in range(width):
    for y in range(height):
        print([next(pixels), next(pixels), next(pixels)])
 

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

 [0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[12, 13, 14]
[15, 16, 17]
[18, 19, 20]
[24, 25, 26]
[0, 0, 0]
[0, 0, 93]
 

Очевидно, что некоторые значения отсутствуют. Почему это происходит? Я что-то упустил?

Ответ №1:

Если изображение RGB с 3 цветовыми каналами загружается в текстурный объект, GL_UNPACK_ALIGNMENT должно быть установлено значение 1:

 gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, iformat, width, height, 0, iformat, gl.GL_UNSIGNED_BYTE, image)
 

GL_UNPACK_ALIGNMENT задает требования к выравниванию для начала каждой строки пикселей в памяти. По умолчанию GL_UNPACK_ALIGNMENT установлено значение 4.
Предполагается, что начало каждой строки изображения выровнено по адресу, кратному 4. Поскольку данные изображения плотно упакованы, а размер каждого пикселя составляет 3 байта, выравнивание необходимо изменить.
Если ширина изображения делится на 4 (точнее, если 3*width делится на 4), то ошибка не заметна.

Поскольку вы считываете текстуру с графического процессора, вам также необходимо изменить GL_PACK_ALIGNMENT :

 gl.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
p = gl.glGetTexImage(gl.GL_TEXTURE_2D, 0, iformat, gl.GL_UNSIGNED_BYTE)
 

Комментарии:

1. Ну, вы можете установить выравнивание упаковки также равным 4 с помощью RGB, если вы добавите байты заполнения в конце каждой строки, чтобы следующая строка начиналась с границы в 4 байта. Или если вы убедитесь, что ширина прямоугольника переданного изображения кратна 4.

2. Спасибо за ответ. Не знал о GL_UNPACK_ALIGNMENT. Ну, еще одна вещь для изучения!

3. Обратите внимание, что вам также необходим GL_PACK_ALIGNMENT glGetTexImage путь обратного чтения в этом конкретном примере.