Есть ли аналогия, которую я могу придумать при сравнении этих разных типов или как это работает?
Кроме того, что означает унифицирование матрицы?
Есть ли аналогия, которую я могу придумать при сравнении этих разных типов или как это работает?
Кроме того, что означает унифицирование матрицы?
Скопировано непосредственно из http://www.lighthouse3d.com/tutorials/glsl-tutorial/data-types-and-variables/. Фактический сайт имеет гораздо более подробную информацию, и было бы полезно проверить.
Переменные квалификаторы
Квалификаторы дают особое значение переменной. Следующие доступны квалификаторы:
- const - объявление имеет постоянную времени компиляции.
- attribute - глобальные переменные, которые могут меняться на вершину, которые передаются из приложения OpenGL в вершинные шейдеры. Этот определитель может использоваться только в вершинных шейдерах. Для шейдера это переменная только для чтения. См. Раздел "Атрибут".
- uniform - глобальные переменные, которые могут изменяться на примитив [...], которые передаются из OpenGL приложение к шейдерам. Этот определитель может использоваться в обеих вершинах и фрагментарные шейдеры. Для шейдеров это переменная только для чтения. См. Раздел "Униформа".
- variable - используется для интерполированных данных между вершинным шейдером и шейдером фрагментов. Доступно для записи в вершинном шейдере и только для чтения в шейдере фрагментов. См. Раздел Varying.
Что касается аналогии, const и равномерность подобны глобальным переменным в C/С++, одна константа, а другая может быть задана. Атрибут - это переменная, которая сопровождает вершину, например, цветные или текстурные координаты. Переменные переменных могут быть изменены вершинным шейдером, но не фрагментарным шейдером, поэтому по сути они передают информацию по конвейеру.
uniform
являются параметрами для каждого примитива (постоянными во время всего вызова отрисовки);attribute
- это параметры для каждой вершины (обычно: положения, нормали, цвета, UV,...);varying
- это параметры на фрагмент (или на пиксель): они различаются от пикселя к пикселю.Важно понять, как varying
работает для программирования ваших собственных шейдеров.
Допустим, вы определяете переменный параметр v
для каждой вершины треangularьника внутри вершинного шейдера. Когда этот изменяемый параметр отправляется фрагментному шейдеру, его значение автоматически интерполируется в зависимости от положения пикселя для рисования.
На следующем изображении красный пиксель получил интерполированное значение переменного параметра v
. Вот почему мы называем их "разными".
Для простоты в приведенном выше примере используется билинейная интерполяция, которая предполагает, что все нарисованные пиксели имеют одинаковое расстояние от камеры. Для точного 3D-рендеринга графические устройства используют корректную в перспективе интерполяцию, которая учитывает глубину пикселя.
В OpenGL "программа" представляет собой набор "шейдеров" (меньших программ), которые связаны друг с другом в конвейере.
// "program" contains a shader pipeline:
// vertex shader -> other shaders -> fragment shader
//
var program = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(program);
Вершины процесса шейдеров (вершинный шейдер), геометрия (геометрический шейдер), тесселяция (тесселяционный шейдер), фрагменты (пиксельный шейдер) и другие задачи пакетного процесса (вычислительный шейдер), необходимые для растеризации трехмерной модели.
Шиндеры OpenGL (WebGL) записываются в GLSL (текстовый шейдерный язык, скомпилированный на GPU).
// Note: As of 2017, WebGL only supports Vertex and Fragment shaders
<!-- Vertex Shader -->
<script id="shader-vs" type="x-shader/x-vertex">
// <-- Receive from WebGL application
uniform vec3 vertexVariableA;
// attribute is supported in Vertex Shader only
attribute vec3 vertexVariableB;
// --> Pass to Fragment Shader
varying vec3 variableC;
</script>
<!-- Fragment Shader -->
<script id="shader-fs" type="x-shader/x-fragment">
// <-- Receive from WebGL application
uniform vec3 fragmentVariableA;
// <-- Receive from Vertex Shader
varying vec3 variableC;
</script>
Шейдеры могут передавать данные в следующий шейдер в конвейере (out
, inout
), а также могут принимать данные из приложения WebGL или предыдущего шейдера (in
).
Шейдеры Vertex и Fragment (любой шейдер действительно) могут использовать переменную uniform
для приема данных из приложения WebGL.
// Pass data from WebGL application to shader
var uniformHandle = gl.glGetUniformLocation(program, "vertexVariableA");
gl.glUniformMatrix4fv(uniformHandle, 1, false, [0.1, 0.2, 0.3], 0);
Vertex Shader также может получать данные из приложения WebGL с помощью переменной attribute
, которая может быть включена или отключена по мере необходимости.
// Pass data from WebGL application to Vertex Shader
var attributeHandle = gl.glGetAttribLocation(mProgram, "vertexVariableB");
gl.glEnableVertexAttribArray(attributeHandle);
gl.glVertexAttribPointer(attributeHandle, 3, gl.FLOAT, false, 0, 0);
Vertex Shader может передавать данные в шейдер фрагмента с использованием переменной varying
. См. Выше код GLSL (varying vec3 variableC;
).
Униформы - это еще один способ передачи данных из нашего приложения на ЦП в шейдеры на GPU, но униформы немного отличаются по сравнению с атрибутами вершин. Прежде всего, униформа носит глобальный характер. Глобальный, означающий, что единообразная переменная является уникальной для каждого объекта программы шейдера и может быть доступна из любого шейдера на любом этапе программы шейдера. Во-вторых, независимо от того, что вы установили для унифицированного значения, униформы будут сохранять свои значения, пока они не будут сброшены или обновлены
Мне нравится описание из https://learnopengl.com/Getting-started/Shaders, потому что слово per-примитив не является интуитивным