OpenGL ES 1.x и 2.x не требуют поддержки трехмерных текстур - см., Например, каноническая справочная страница для glBindTexture
, в которой в качестве целей указываются только GL_TEXTURE_2D
и GL_TEXTURE_CUBE_MAP
, а для оборудования iOS нет подходящего расширения.
Лучшее решение, которое я смог придумать, - это упаковать трехмерную текстуру, как если бы это была двухмерная текстура, так что вы должны сказать, что это 128x128x128 3d-текстура, и вы выкладываете ее как 128 отдельных 128x128 изображений в виде Сетка 16х8 на одной 2d текстуре. Таким образом, 2d текстура имеет размер 2048x1024 пикселей, приближаясь к аппаратному пределу на устройствах iPhone 4 и iPad 2 и устройствах iOS, совместимых с ES 2.0, которые предшествовали им.
Затем вы подаете координату 3d-текстуры в ваш фрагментный шейдер точно так, как если бы был способ индексировать 3d-текстуры изначально, но выполняете небольшую математическую операцию, чтобы свернуть ее до 2d.
Итак, в примере 128x128x128 вы бы сделали что-то вроде (закодировано здесь, как я говорю, непроверено):
texPos.x = sourceVarying.x / 16.0; // because we've packed 16 source images across,
texPos.y = sourceVarying.y / 8.0; // and 8 images down
// we'll multiply z by 16 since then, logically, the integer part is
// how many tiles across to index, and the decimal part is now many
// tiles down to index
texPos.z *= 16.0;
// figure out how many tiles across to index, with each tile being
// 1.0 / 16.0 in size
texPos.x += floor(texPos.z) / 16.0;
// remove the integer part of z, then multiply by 8 to do much what
// we just did to y
texPos.z = fract(texPos.z) * 8.0;
texPos.y += floor(texPos.z) / 8.0;
// now load the appropriate sample from texPos.xy
Вероятно, это не самый эффективный способ достижения этого, он написан для (относительной) ясности. Вы также видите существенный недостаток производительности, связанный с зависимостью каждого чтения текстуры (т. Е. Графический процессор не может предсказать доступ за пределами фрагментного шейдера, что приводит к значительным трудностям конвейера). Но это должно быть сопоставлено с любыми затратами, которые вы должны будете потратить, чтобы использовать что-то, кроме карт текстур 3d.
Обратите внимание, что вы делаете один доступ, связанный с конкретным z-срезом. Таким образом, вы ограничены выборкой типа GL_NEAREST
хотя бы в одном измерении, если вы не хотите делать две выборки и смешивать результат самостоятельно с еще большими затратами. Я также ничего не делал с зажимами, к которым вы, возможно, захотите обратиться.
Datenwolf (+1, между прочим) также совершенно прав насчет того, что проблема заключается в мипмаппинге; Я просто отключил его.
Приложение конца 2013 года: на момент написания этой статьи, iOS 7, iPhone 5s, iPad Mini второго поколения и iPad Air - все поддерживают ES 3.0. 3.0 вводит цель GL_TEXTURE_3D
. Таким образом, вы можете использовать трехмерное текстурирование непосредственно на этих устройствах и, возможно, на всех будущих устройствах iOS. И, к сведению, он видит аналогичную доступность на Android, поскольку поддерживается всеми последними устройствами Nexus, HTC One, несколькими последними Samsungs и другими.