Чтобы понять, что делает glTexStorage
, вам необходимо понять, что делают функции glTexImage*
.
glTexImage2D
выполняет три действия:
- Он выделяет хранилище OpenGL дляопределенный слой MIPMAP, с определенным размером.Например, вы можете выделить двухмерное изображение 64x64 в качестве уровня mipmap 2.
- Он устанавливает внутренний формат для уровня mipmap.
- Он загружает данные пикселей в текстуру.Последний шаг не является обязательным;если вы передадите NULL в качестве значения указателя (и ни один буферный объект не будет привязан к
GL_PIXEL_UNPACK_BUFFER
), тогда передача пикселя не будет.
Для создания текстуры с разметкой вручную требуется последовательность glTexImage
звонки, по одному на каждый уровень mipmap.Каждый из размеров уровней mipmap должен соответствовать размеру предыдущего уровня.
Теперь, если вы посмотрите на раздел 3.9.14 спецификации GL 4.2, вы увидите две страницы правилчто объект текстуры должен следовать, чтобы быть «завершенным».К объекту текстуры, который является неполным, нельзя получить доступ.
Среди этих правил есть такие вещи, как "mipmaps должны иметь соответствующий размер".Возьмите пример, который я привел выше: 2D-изображение 64x64, которое является уровнем 2 mipmap. Было бы совершенно правильный код OpenGL для выделения уровня 1 mipmap, который использовал текстуру 256x256.Или 16х16.Или 10х345.Все это было бы совершенно функционально с точки зрения исходного кода.Очевидно, что они будут создавать чепуху как текстуру, так как текстура будет неполной.
Снова рассмотрим mipmap 64x64 2. Я создаю его как свое первое изображение.Теперь я мог бы создать mipmap 128x128 1. Но я мог бы также создать mipmap 128x12 9 1. Оба они полностью согласованы с размером 2x64x64 mipmap (размеры mipmap всегда округляются вниз).Хотя они оба согласованы, они оба разных размеров.Если драйвер должен выделить всю цепочку mipmap сразу (что вполне возможно), какой размер он выделяет?Это не знает.Он не может знать, пока вы явно не выделите остальные.
Вот еще одна проблема.Допустим, у меня есть текстура с полной цепочкой mipmap.Это полностью текстура, в соответствии с правилами.А потом я снова звоню glTexImage2D
.Что теперь?Я мог случайно изменить внутренний формат.Каждый уровень mipmap имеет отдельный внутренний формат;если они не все согласны, то текстура является неполной.Я мог случайно изменить размер текстуры, снова сделав текстуру неполной.
glTexStorage
предотвращает все эти возможные ошибки .Он создает все нужные вам карты, учитывая размер базового уровня.Он распределяет все эти мипмапы с одинаковым форматом изображения, так что вы не можете это испортить.Это делает текстуру неизменной , так что вы не можете прийти и попытаться сломать текстуру с помощью плохого glTexImage2D
вызова.И это предотвращает другие ошибки, которые я даже не удосужился скрыть.
Вопрос не в том, что делает glTexStorage?Вопрос в том, «почему мы так долго без этого».
glTexStorage
не имеет отношения к glGenerateMipmap
;они являются ортогональной функциональностью.glTexStorage
делает именно то, что говорит: он выделяет текстуру память место.Это не заполняет это пространство ничем.Таким образом, он создает текстуру с заданным размером, заполненную неинициализированными данными.Так же, как glRenderbufferStorage
выделяет буфер рендеринга с заданным размером, заполненным неинициализированными данными.Если вы используете glTexStorage
, вам необходимо загрузить данные с glTexSubImage
(поскольку glTexImage
запрещена для неизменной текстуры).
glTexStorage
создает пространство для mipmaps.glGenerateMipmap
создает сами данные mipmap (меньшие версии базового слоя).Он также может создавать пространство для mipmaps, если это пространство еще не существует.Они используются для двух разных вещей.