Как обработать 3d текстуру в webgl2

Я пытаюсь работать с 3D-текстурой в webgl2, и я узнал о

gl.texImage3D();

У меня есть опыт работы с 2-мерными текстурами, и мне это показалось очень удобным, но есть и другой подход, который люди используют в Интернете.


gl.texStorage3D()

а потом,

gl.texSubImage3D() // with all offset of x,y and z as 0.

Я просто хочу знать, в чем разница между этими двумя подходами. Я узнал, что эквивалент второго варианта доступен и для 2D-текстуры, но я не использую его для передачи данных цели. Я знаю, что фрагмент изображения предназначен для создания фрагмента изображения текстуры для фрагментного шейдера, но я не понимаю, в чем разница между двумя подходами.


person pravin poudel    schedule 11.08.2020    source источник


Ответы (1)


Краткий ответ - texStorage2D и texStorage3D выделить всю текстурную память заранее. Где texImage2D и texImage3D выделяют по одному уровню MIP за раз.

texSubImage2D и texSubImage3D ничего не выделяют. Они просто копируют данные на mip-уровень текстуры, который ранее был назначен одной из вышеперечисленных функций.

Что касается того, почему то или другое. texStorage2D и texStorage3D могут немедленно выделять память на GPU. texImage2D и texImage3D не могут, поскольку они не знают полную текстуру (все mips), пока вы действительно не попытаетесь что-то нарисовать с помощью текстуры. Другими словами, texStorage2D/3D может быть более эффективным, если texImage2D/3D более гибким.


Для того, чтобы текстура могла быть визуализирована, все уровни mip, которые вы собираетесь использовать, должны иметь один и тот же внутренний формат и правильные размеры.

Когда вы вызываете texStorage2D/3D, вы сообщаете размер уровня MIP 0 (самый большой уровень) и сколько всего уровней MIP нужно выделить. Допустим, вы указываете ему внутренний формат gl.RGBA8, ширину и высоту 8 и 4 уровней MIP.

gl.texStorage2D(gl.TEXTURE_2D,
                4,         // 4 levels
                gl.RGBA8,  // internal format
                8,         // width
                8);        // height
                

Он будет выделять mip-уровни 8x8x4, 4x4x4, 2x2x4, 1x1x4, все 4 уровня mip. Он знает, что все они RGBA8. Он знает, что все они подходящего размера. Текстуры, выделенные с помощью texStorage2D, не могут быть изменены по размеру или внутреннему формату. Если вы попытаетесь вызвать texImage2D для текстуры, созданной с помощью texStorage2D, вы получите сообщение об ошибке.

Если вы вместо этого сначала хорошо использовали texImage2D, вы, вероятно, укажете первый mip

gl.texImage2D(gl.TEXTURE_2D, 
              0,         // mip level
              gl.RGBA8,  // internal format
              8,         // width
              8,         // height
              0,         // border
              gl.RGBA,   // data format
              gl.UNSIGNED_BYTE,  // data type
              data);

Итак, теперь у вас есть только 1 уровень mip, уровень # 0. Вы добавите еще 3 мипа? Они будут подходящего размера? Будут ли эти 3 MIP-формата иметь такой же внутренний формат? Вы измените уровень MIP # 0 на что-то другое, другой размер или другой внутренний формат? WebGL не знает, какой будет ваша следующая команда, ему нужно дождаться, пока вы действительно попытаетесь нарисовать текстуру, прежде чем он сможет проверить. С texStorage вы заранее определяете размеры и форматы всех mips, поэтому вам нужно проверить только один раз. С texImage вы не сообщаете ему все заранее, поэтому он должен снова проверить во время отрисовки, если что-то изменится.

person gman    schedule 11.08.2020
comment
Спасибо за ваш ответ. Вы имеете в виду, что texStorage заранее выделяет память для разных уровней, а texImage2D выделяет при вызове отрисовки, верно? Я не понимаю, почему вы говорите, что texStorage эффективен, поскольку он может занимать место в памяти для уровня, который не может использоваться, и я не понимаю, насколько texImage гибок, чем texStorage. - person pravin poudel; 11.08.2020
comment
Если вы задумаетесь о последствиях использования API, вы сможете понять это самостоятельно, но я добавил больше информации. - person gman; 11.08.2020
comment
это очень полезная информация, которая в значительной степени помогла мне прояснить мое замешательство. Большое спасибо за ваши усилия и время. - person pravin poudel; 11.08.2020