Есть ли аналогия, которую я могу придумать, сравнивая эти разные типы, или как они работают?
Кроме того, что означает униформа матрицы?
Ответы:
Скопировано прямо с http://www.lighthouse3d.com/tutorials/glsl-tutorial/data-types-and-variables/ . Фактический сайт содержит гораздо более подробную информацию, и его стоит проверить.
Квалификаторы переменных
Квалификаторы придают переменной особое значение. Доступны следующие квалификаторы:
- const - Объявление константы времени компиляции.
- attribute - Глобальные переменные, которые могут изменяться для каждой вершины, которые передаются из приложения OpenGL в вершинные шейдеры. Этот квалификатор можно использовать только в вершинных шейдерах. Для шейдера это переменная только для чтения. См. Раздел Атрибуты.
- uniform - Глобальные переменные, которые могут изменяться для [...] примитива, которые передаются из приложения OpenGL шейдерам. Этот квалификатор можно использовать как в вершинных, так и в фрагментных шейдерах. Для шейдеров это переменная только для чтения. См. Раздел «Униформа».
- варьирующийся - используется для интерполированных данных между вершинным шейдером и фрагментным шейдером. Доступно для записи в вершинном шейдере и только для чтения во фрагментном шейдере. См. Раздел «Варьирование».
Что касается аналогии, const и uniform похожи на глобальные переменные в C / C ++, одна постоянна, а другая может быть установлена. Атрибут - это переменная, которая сопровождает вершину, например координаты цвета или текстуры. Варьирующие переменные могут быть изменены вершинным шейдером, но не фрагментным шейдером, поэтому, по сути, они передают информацию по конвейеру.
uniform
являются примитивными параметрами (постоянными в течение всего вызова отрисовки);attribute
параметры для каждой вершины (обычно: позиции, нормали, цвета, UV, ...);varying
параметры для каждого фрагмента (или для каждого пикселя ): они варьируются от пикселей к пикселям.Важно понимать, как varying
работает программирование собственных шейдеров.
Допустим, вы определяете переменный параметр v
для каждой вершины треугольника внутри вершинного шейдера . Когда этот изменяющийся параметр отправляется фрагментному шейдеру , его значение автоматически интерполируется в зависимости от положения пикселя для рисования.
На следующем изображении красный пиксель получил интерполированное значение изменяющегося параметра v
. Вот почему мы называем их «разными».
Для простоты в приведенном выше примере используется билинейная интерполяция , которая предполагает, что все нарисованные пиксели находятся на одинаковом расстоянии от камеры. Для точного 3D-рендеринга графические устройства используют интерполяцию с коррекцией перспективы, которая учитывает глубину пикселя.
noperspective
чтобы получить простую билинейную интерполяцию, а не интерполяцию с правильной перспективой (определяется квалификатором по умолчанию:) smooth
. См. Этот пример .
В чем разница между атрибутом, униформой и переменной в WebGL?
В OpenGL «программа» - это набор «шейдеров» (небольших программ), которые соединены друг с другом в конвейер.
// "program" contains a shader pipeline:
// vertex shader -> other shaders -> fragment shader
//
const program = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(program);
Шейдеры обрабатывают вершины (вершинный шейдер), геометрию (геометрический шейдер), тесселяцию (тесселяционный шейдер), фрагменты (пиксельный шейдер) и другие задачи пакетной обработки (вычисление шейдера), необходимые для растеризации 3D-модели.
Шейдеры 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
).
Вершинные и фрагментные шейдеры (на самом деле любой шейдер) могут использовать uniform
переменную для получения данных из приложения WebGL.
// Pass data from WebGL application to shader
const 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
const attributeHandle = gl.glGetAttribLocation(mProgram, "vertexVariableB");
gl.glEnableVertexAttribArray(attributeHandle);
gl.glVertexAttribPointer(attributeHandle, 3, gl.FLOAT, false, 0, 0);
Вершинный шейдер может передавать данные во фрагментный шейдер с помощью varying
переменной. См. Код GLSL выше ( varying vec3 variableC;
).
Униформы - это еще один способ передачи данных из нашего приложения на CPU шейдерам на GPU, но униформы немного отличаются от атрибутов вершин. Во-первых, униформа глобальна. Глобальная, что означает, что универсальная переменная уникальна для каждого объекта программы шейдера и может быть доступна из любого шейдера на любом этапе программы шейдера. Во-вторых, какое бы значение вы ни установили для униформы, униформы сохранят свои значения до тех пор, пока они не будут сброшены или обновлены.
Мне нравится описание с https://learnopengl.com/Getting-started/Shaders , потому что слово per-primitive не интуитивно понятно