Почему так много функций для настройки Uniforms?
glUniform1f glUniform2f glUniform3f glUniform4f
glUniform1fv glUniform2fv glUniform3fv glUniform4fv
glUniform1i glUniform2i glUniform3i glUniform4i
glUniform1iv glUniform2iv glUniform3iv glUniform4iv
glUniform1ui glUniform2ui glUniform3ui glUniform4ui
glUniform1uiv glUniform2uiv glUniform3uiv glUniform4uiv
glUniformMatrix2fv glUniformMatrix2x3fv glUniformMatrix2x4fv
glUniformMatrix3fv glUniformMatrix3x2fv glUniformMatrix3x4fv
glUniformMatrix4fv glUniformMatrix4x2fv glUniformMatrix4x3fv
Я думаю, что способ загрузки данных в буферы вершин и элементов лучше, так как мне не нужно вызывать другую функцию для другого типа.
Почему это так с униформой? Есть ли возможность использовать только одну функцию, где я могу просто передать указатель?
Задним числом всегда 20/20, и выбор был сделан, чтобы соответствовать другим функциям, которые принимают векторные данные в различных типах и размерности. Я имею в виду glVertex … конечно. Теперь первоначальная причина передачи по значению заключалась в том, что на некоторых архитектурах имеется достаточно регистров, чтобы было эффективнее передавать по значению в регистр. Также компиляторы могут оптимизировать предыдущие операции, чтобы получить правильные значения в правильном регистре.
OpenGL является потомком IrixGL, разработанным SGI для своих графических рабочих станций и операционной системы Irix. Эти рабочие станции использовали архитектуру MIPS. И соглашение о вызовах для MIPS является (https://en.wikipedia.org/wiki/Calling_convention#MIPS)
Наиболее часто используемым [5] соглашением о вызовах для 32-битных MIPS является ABI O32 [6], который передает первые четыре аргумента функции в регистрах $ a0- $ a3; …
…
ABI N32 и N64 передают первые восемь аргументов функции в регистрах $ a0- $ a7; …
Итак, у вас есть это: на MIPS это довольно разумный выбор для передачи элементов vec4 на значение. Особенно в IrixGL и OpenGL-1.0, где не было массивов вершин, и вам пришлось бы совершать множество вызовов glVertex.
Если вы используете современный OpenGL, вы можете использовать Объекты однородного буфера, которые были доступны начиная с OpenGL 3.1.
Тем не менее, требуется немного больше «настройки». В частности, они требуют, чтобы вы создавали свои шейдеры особым образом (определяя единообразные блоки). Вам также необходимо определить макет памяти (std140
является популярным) для блоков или, в качестве альтернативы, запрашивает компоновки, чтобы определить, как должны быть отформатированы данные вашего унифицированного буфера, чтобы привязка соответствовала формату, ожидаемому графическим процессором.
После того, как все настройки выполнены, привязка выполняется с помощью вызова: glBindBuffer(GL_UNIFORM_BUFFER, <name>)
так же, как вершины и индексные потоки.
Это было отмечено в ходе обсуждения GL_ARB_shader_objects:
15) Существует вероятность огромного взрыва униформы груза.
команды, что делать?ОБСУЖДЕНИЕ. Нам нужно иметь возможность загружать vec1, vec2, vec3 или vec4, или
массивы vec1, массивы vec2, массивы vec3 или массивы vec4.
Кроме того, необходимо также загружать матрицы 2×2, 3×3 и 4×4,
и массивы 2×2, массивы 3×3 и массивы матриц 4×4. Вход
Значения команд загрузки униформ могут (традиционный OpenGL) входить в
байты, шорты, целые числа, числа с плавающей запятой, двойные и беззнаковые байты, шорты без знака
и неподписанные целые.РЕШЕНИЕ: предлагаемое подмножество в новых процедурах и функциях
раздел ниже.
Подмножество, о котором идет речь, является тем, которое было ратифицировано:
void Uniform1fARB(int location, float v0)
void Uniform2fARB(int location, float v0, float v1)
void Uniform3fARB(int location, float v0, float v1, float v2)
void Uniform4fARB(int location, float v0, float v1, float v2, float v3)
void Uniform1iARB(int location, int v0)
void Uniform2iARB(int location, int v0, int v1)
void Uniform3iARB(int location, int v0, int v1, int v2)
void Uniform4iARB(int location, int v0, int v1, int v2, int v3)
void Uniform1fvARB(int location, sizei count, const float *value)
void Uniform2fvARB(int location, sizei count, const float *value)
void Uniform3fvARB(int location, sizei count, const float *value)
void Uniform4fvARB(int location, sizei count, const float *value)
void Uniform1ivARB(int location, sizei count, const int *value)
void Uniform2ivARB(int location, sizei count, const int *value)
void Uniform3ivARB(int location, sizei count, const int *value)
void Uniform4ivARB(int location, sizei count, const int *value)
void UniformMatrix2fvARB(int location, sizei count, boolean transpose, const float *value)
void UniformMatrix3fvARB(int location, sizei count, boolean transpose, const float *value)
void UniformMatrix4fvARB(int location, sizei count, boolean transpose, const float *value)
Вызовы беззнаковых целых и неквадратных матриц были добавлены позже.
Я думаю, что @datenwolf не скрывает, что glVertex
В семействе вызовов было много функций для оптимизации передачи по значению в регистрах, с другой стороны, установка униформ должна происходить на несколько порядков реже, чем передача вершин, поэтому я не думаю, что производительность здесь является реальной проблемой ,
«Следуйте уже установленному API» звучит как более разумное объяснение.
Кроме того, вам действительно нравится передавать типы данных через void *
интерфейсы? То, что вы спрашиваете, это как API
glUniform(GLint location, GLenum datatype, GLsizei count, const GLvoid *data)
GL уже полон таких уровней ломкости и небезопасности типов (привет, нетипизированный GLenum
s!), я бы предпочел API, которые не добавляют больше этого.
Что аппаратное обеспечение должно сделать в зависимости от унифицированного формата данных, может отличаться.
То, что вы спрашиваете, заключается в том, что потенциальные переключатели / если серии реализованы в драйвере GL. Затем вам придется платить за эту стоимость за каждое использование API, даже если приложение уже точно знает, какую форму он собирается установить. Это не будет эффективным дизайном API (несмотря на тот факт, что на самом деле передача буфера униформ в наши дни намного эффективнее. Это было не так, когда разрабатывался этот API).
По этой причине glVertex3f и соавт. был такой дизайн API тоже. Но, по крайней мере, те не генерировали ошибки. Для Uniforms это немного непонятно, поскольку они определенно генерируют ошибки, поэтому код не может быть полностью минимальным.