Техника OpenGL может быть невероятно непрозрачной и запутанной. Я знаю! Я пишу 3D движки на основе OpenGL в течение многих лет (время от времени). В моем случае часть проблемы заключается в том, что я пишу движок, чтобы скрыть базовый 3D API (OpenGL), поэтому, когда я что-то получаю, я больше никогда не вижу код OpenGL.
Но вот одна из техник, которая помогает моему мозгу постичь «путь OpenGL». Я думаю, что этот способ мышления является правдой (но не всей историей).
Подумайте об аппаратной графике / видеокартах. У них есть определенные возможности, реализованные в оборудовании. Например, графический процессор может обновлять (записывать) только одну текстуру за раз. Тем не менее, обязательно, чтобы графический процессор содержал много текстур в оперативной памяти внутри графического процессора, поскольку передача между памятью процессора и памятью графического процессора очень медленная.
Итак, API OpenGL создает понятие «активной текстуры». Затем, когда мы вызываем функцию API OpenGL для копирования изображения в текстуру, мы должны сделать это следующим образом:
1: generate a texture and assign its identifier to an unsigned integer variable.
2: bind the texture to the GL_TEXTURE bind point (or some such bind point).
3: specify the size and format of the texture bound to GL_TEXTURE target.
4: copy some image we want on the texture to the GL_TEXTURE target.
И если мы хотим нарисовать изображение на другой текстуре, мы должны повторить тот же процесс.
Когда мы наконец готовы что-то отобразить на дисплее, нам нужен наш код, чтобы сделать одну или несколько текстур, которые мы создали, и скопировать изображения, чтобы они стали доступны нашему фрагментному шейдеру.
Как выясняется, фрагментный шейдер может получить доступ к более чем одной текстуре одновременно, используя несколько «текстурных блоков» (по одной текстуре на текстурный блок). Итак, наш код должен связать текстуры, которые мы хотим сделать доступными для текстурных блоков, к которым наши фрагментные шейдеры ожидают их привязки.
Итак, мы должны сделать что-то вроде этого:
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, mytexture0);
glActiveTexture (GL_TEXTURE1);
glBindTexture (GL_TEXTURE_2D, mytexture1);
glActiveTexture (GL_TEXTURE2);
glBindTexture (GL_TEXTURE_2D, mytexture2);
glActiveTexture (GL_TEXTURE3);
glBindTexture (GL_TEXTURE_2D, mytexture3);
Теперь я должен сказать, что я люблю OpenGL по многим причинам, но этот подход сводит меня с ума. Это потому, что все программное обеспечение, которое я писал годами, выглядело бы так:
error = glSetTexture (GL_TEXTURE0, GL_TEXTURE_2D, mytexture0);
error = glSetTexture (GL_TEXTURE1, GL_TEXTURE_2D, mytexture1);
error = glSetTexture (GL_TEXTURE2, GL_TEXTURE_2D, mytexture2);
error = glSetTexture (GL_TEXTURE3, GL_TEXTURE_2D, mytexture3);
БАМО. Нет необходимости устанавливать все это состояние снова и снова. Просто укажите, к какому блоку текстуры прикрепить текстуру, плюс тип текстуры, чтобы указать, как получить доступ к текстуре, а также идентификатор текстуры, которую я хочу прикрепить к блоку текстуры.
Мне также не нужно было бы привязывать текстуру как активную текстуру, чтобы скопировать на нее изображение, я бы просто дал идентификатор текстуры, на которую я хотел скопировать. Почему это должно быть связано?
Что ж, есть одна загвоздка, которая заставляет OpenGL структурироваться таким безумным образом. Поскольку аппаратные средства выполняют некоторые функции, а программный драйвер - другие функции, а также то, что делается в зависимости от переменной (зависит от карты GPU), им необходим какой-то способ держать сложность под контролем. По сути, их решение состоит в том, чтобы иметь только одну точку привязки для каждого типа сущности / объекта и требовать, чтобы мы связывали наши сущности с этими точками привязки, прежде чем мы вызовем функции, которые ими манипулируют. И в качестве второй цели, связывание сущностей - это то, что делает их доступными для GPU и наших различных шейдеров, которые выполняются в GPU.
По крайней мере, так я держу "путь OpenGL" прямо в моей голове. Честно говоря, если кто-то действительно, действительно, ДЕЙСТВИТЕЛЬНО понимает все причины, по которым OpenGL (и должен быть) структурирован таким, какой он есть, я бы хотел, чтобы он опубликовал свой собственный ответ. Я считаю, что это важный вопрос и тема, и обоснование редко, если вообще когда-либо описывается, и тем более не так, как мой маленький мозг может понять.