OpenGL4.5 - связать несколько текстур и сэмплеров

введите описание изображения здесь

Я пытаюсь понять текстуры, текстурные блоки и семплеры в OpenGL 4.5. Я прилагаю изображение того, что я пытаюсь понять. Я думаю в моем примере все правильно, а вот насчёт 1D Sampler справа со знаком вопроса не уверен.

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

Каждая из этих точек привязки может поддерживать одну из целей каждой текстуры (в моем случае я привязываю цели GL_TEXTURE_2D и GL_TEXTURE_1D к точке привязки 0, а другую GL_TEXTURE_2D к точке привязки 1).

Кроме того, сэмплеры могут быть привязаны к этим точкам привязки почти таким же образом (я привязал 2D-сэмплер к точке привязки 0 на рисунке).

Функции для выполнения этих операций — glBindTextureUnit и glBindSampler.

Моей первоначальной мыслью было также привязать одномерный сэмплер к точке привязки 0, а в стране шейдеров выполнить сопоставление на основе точки привязки и типа сэмплера:

layout (binding = 0) uniform sampler1D tex1D;
layout (binding = 0) uniform sampler2D tex2D;

Цитирую источник:

Каждый блок изображения текстуры поддерживает привязки ко всем целям. Таким образом, 2D-текстура и текстура-массив могут быть связаны с одним и тем же элементом изображения, или разные 2D-текстуры могут быть связаны с двумя разными элементами изображения, не влияя друг на друга. Итак, какая текстура используется при рендеринге? В GLSL это зависит от типа сэмплера, который использует эту единицу изображения текстуры.

но я нашел следующее утверждение:

[..] звучит подозрительно, как будто вы можете использовать один и тот же блок изображения текстуры для разных сэмплеров, если они имеют разные типы текстур. Не делай это. Спецификация явно запрещает это; если два разных сэмплера GLSL имеют разные типы текстур, но связаны с одним и тем же блоком изображения текстуры, то рендеринг завершится ошибкой. Дайте каждому сэмплеру разные единицы изображения текстуры.

Итак, мой вопрос: какова цель привязки разных целей текстуры к одной и той же точке привязки, если в конечном итоге один сэмплер будет привязан к этой точке привязки, заставляя вас выбирать?

Информация, которую я цитирую: https://www.khronos.org/opengl/wiki/Texture#Texture_image_units


person Carlos Romero    schedule 21.07.2017    source источник


Ответы (2)


Так почему же это существует? Что ж...

Когда-то текстурных блоков не было (поэтому glActiveTexture — отдельная функция от glBindTexture). Действительно, в OpenGL 1.0 не было даже текстурных объектов. Но по-прежнему должны были быть разные виды текстур. Вам по-прежнему нужно было иметь возможность создавать данные для 2D-текстуры и 3D-текстуры. Поэтому они придумали различие между целевыми текстурами и использовали glEnables, чтобы определить, какая цель будет использоваться в операции рендеринга.

Когда в GL 1.1 появились текстурные объекты, они должны были определить отношения между текстурным объектом и целью. Они решили, что как только объект был привязан к цели, он навсегда ассоциировался с этой целью. Из-за вышеупомянутой необходимости иметь несколько текстур разных типов со старой функциональностью включения было решено, что каждая цель представляет собой отдельную точку привязки объекта. И заставили повторить точку привязки в glBindTexture, чтобы читателю кода было ясно, данные какой точки привязки вы нарушили.

Переход к OpenGL 1.2, когда вышла мультитекстура. Так что теперь им нужно, чтобы вы могли привязывать несколько текстур одной и той же цели, но к разным «юнитам». Но они не могли изменить glBindTexture, чтобы указать конкретную единицу измерения; это было бы обратно несовместимым изменением.

Теперь они могли бы полностью изменить работу текстур, создав новую функцию привязки специально для мультитекстурирования и тому подобного. Но OpenGL ARB любит обратную совместимость; им нравится заставлять работать старые функции API, независимо от того, как выглядит получившийся API. Поэтому вместо этого они решили, что текстурный модуль будет полным набором привязок, причем каждый набор будет иметь состояние включения, указывающее, какая цель должна быть использована. И вы переключаетесь между юнитами с помощью glActiveTexture.

Конечно, как только появились шейдеры, вы можете видеть, как все это меняется. Состояние включения становится типом семплера в шейдере. Итак, теперь нет явного кода, описывающего, какая цель текстуры включена; это просто шейдеры. Поэтому им пришлось ввести правило, согласно которому два семплера не могут использовать одно и то же устройство, если они разных типов.

Вот почему каждый текстурный блок имеет несколько независимых точек привязки: приверженность OpenGL обратной совместимости.

Лучше игнорировать существование этой возможности. Привяжите правильные текстуры, которые нужны вашему конкретному шейдеру. Поэтому сосредоточьтесь на использовании этих функций и не беспокойтесь о том, что у вас могут быть две текстуры, привязанные к одной и той же цели. Если вы хотите убедиться, что вы случайно не используете неправильную текстуру, вы можете использовать glBindTextures или glBindTextureUnit с именем текстуры 0, что отменит привязку всех целей в конкретном(ых) текстурном блоке(ах).

person Nicol Bolas    schedule 21.07.2017
comment
Можете ли вы показать пример muti-bind для OpenGL 3.3? glBindTextures и glBindTextureUnit существуют только для OGL4.5. Сегодня существует множество аппаратных средств, которые не позволяют использовать эту версию. - person Ripi2; 21.07.2017
comment
@Ripi2: Буквально первое слово в названии — OpenGL4.5. Итак, ясно, что ОП спрашивает об OpenGL версии 4.5, поэтому нет необходимости предлагать альтернативу 3.3. Кроме того, вопрос помечен opengl-4, поэтому снова 3.3 здесь не имеет смысла. - person Nicol Bolas; 21.07.2017
comment
@Ripi2: Кроме того, в GL 4.4 к ядру была добавлена ​​​​мульти-связка. И это расширение также поддерживается на некоторых устройствах класса 3.3. Даже ARB_DSA имеет некоторую поддержку на оборудовании 3.3. - person Nicol Bolas; 21.07.2017
comment
@NicolBolas спасибо за ваш ответ. Итак, вкратце, к юнит-текстуре подключайте исключительно а) одну текстуру и б) одиночный сэмплер, причем обе должны совпадать по размерности. Это правильно? У меня есть Руководство по программированию 4.5, и я стараюсь придерживаться его (на самом деле там даже не упоминается glActiveTexture), а в описании для glBindTextureUnit не сказано, что он отвязывает все остальные цели для данного текстурного блока (второй эффект вы упомянули в первом абзаце). - person Carlos Romero; 21.07.2017
comment
@CarlosRomero: Да, ты прав. Я неправильно прочитал спецификацию как для glBindTextureUnit, так и для glBindTextures. Ни один из них не отвязывает текстуры от других целей в этом текстурном блоке, если только вы явно не привязываете 0 к этому блоку. - person Nicol Bolas; 21.07.2017
comment
Я вижу, спасибо! Это проясняет. Небольшое что-то - я думаю glBindTextures обратно совместимо? Так что правильно (если придерживаться 4.5 / большой толстой книги) было бы позвонить glBindTextureUnit(unit, 0)? - person Carlos Romero; 21.07.2017
comment
@CarlosRomero: glBindTextures делает то же, что и glBindTextureUnit, только для нескольких текстур одновременно. - person Nicol Bolas; 21.07.2017

person    schedule
comment
glUniform1i(locationProgA_forSampler1D, GL_TEXTURE0 + 1); Это не так. И даже если мы проигнорируем эту ошибку, то, о чем вы говорите, вы никогда не должны делать. Это чрезвычайно подверженный ошибкам код. - person Nicol Bolas; 21.07.2017
comment
@NicolBolas Спасибо, что указали на эту ошибку. Исправлено сейчас. Конечно, Второй вариант подвержен ошибкам. Это просто объяснение ОП об этих явно противоречащих друг другу предложениях. - person Ripi2; 21.07.2017