2015-03-02 6 views
0

Я пытаюсь понять, как шейдеры вершин и фрагментов работают в OpenGL ES 2.0.Настройка векторов в шейдерах, как это работает? OpenGL GLSL

Мои шейдеры выглядеть следующим образом:

вершинные шейдеры:

// source code for the vertex shader 
attribute vec4 vPosition 
attribute vec2 a_texCoord; 
varying vec2 v_texCoord; 

void main() { 
    gl_Position = vPosition; 
    v_texCoord = a_texCoord; 
} 

пиксельный шейдер:

// source code for the fragment shader 
precision mediump float; 
uniform sampler2D s_texture; 
varying vec2 v_texCoord; 

void main() { 
    gl_FragColor = texture2D(s_texture, v_texCoord); 
} 

Программа, которая использует эти шейдеры рисует простой 2D прямоугольник текстура (изображение). Сначала он передает вершины прямоугольника и текстурные коорды в вершинный шейдер с атрибутами. Затем вершинный шейдер передает текстурные координаты с изменением на фрагментарный шейдер.

Что меня смущает, так это то, что векторы vPosition, a_texCoord и v_texCoord могут сохранять только 1 очко, но должны сохранять 4 разных точки. Я где-то читал, что вершинный шейдер будет вызываться для каждой вершины. Означает ли это, что шейдеры вершин и фрагментов будут обработаны 4 раза для каждого изображения, которое я хочу рисовать? Когда я определяю атрибуты (glVertexAttribPointer), я использую массив с 4 точками, как шейдеры могут сохранять 4 точки в переменной, которая может хранить только 1 балл?

Я хочу использовать форму вместо атрибутов, я читаю ее лучше. Также мне не нужна переменная переменная. Я хотел бы иметь это так:

вершинный шейдер:

// source code for the vertex shader 
uniform vec4 vPosition; 

void main() { 
    gl_Position = vPosition; 
} 

фрагмент шейдера:

// source code for the fragment shader 
precision mediump float; 
uniform sampler2D s_texture; 
uniform vec2 v_texCoord; 

void main() { 
    gl_FragColor = texture2D(s_texture, v_texCoord); 
} 

Возможно ли это? Могу ли я передать все точки, которые нужны мне шейдерам? Это хорошая идея?

ответ

1

Нет, вы не можете хранить данные вершин в форме. Единица предназначена для каждого вызова, и атрибут вершины предназначен для каждой вершины. Единственный способ, которым вы могли бы использовать свою вершинную позицию с униформой, - это рисовать точку, поскольку она использует только одну координату.

Так что о вершинах и обработке: Да, если вы нарисуете с 4 вершинами, будет выполнено не менее 4 вызовов вашего вершинного шейдера для тех вершин, которые будут обработаны. Вам не о чем беспокоиться, представьте себе, что при рисовании изображения 100x100 с использованием 4 вершин будет 4 вызова вершинного шейдера и 10000 (100x100) звонков в шейдер фрагмента. Это то, для чего предназначен графический процессор, он делает это чрезвычайно эффективно.

Вы можете посмотреть на некоторых полных картах OPENGL трубопроводов, чтобы понять все лучше, но только, чтобы дать вам подсказку о том, что происходит, когда вы вызываете OPENGL рисовать:

  • В зависимости от формы вас (например, треугольники), количество точек будет приниматься и обрабатываться в вершинном шейдере, это включает в себя все атрибуты, такие как положение, координаты текстуры, нормали ...
  • Далее произойдет растеризация, с которой все пиксели на будет определено, что буфер будет нарисован и для каждого из них будет назначен фрагментарный шейдер.
  • Затем происходит фрагментарный шейдер, который получит все интерполированные значения и фиксированную униформу, которые ему нужны, и обновить один конкретный пиксель в каждом подключенном буфере, который вы используете (цвет, глубина ...).

Теперь снова в этом конвейере есть намного больше, чем описано ниже, но это наиболее интересно для вопросов, которые вы задаете.

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

Для того, чтобы понять, что происходит из созданных вами шейдеров: если вы рисуете текстурированный прямоугольник, у вас будет 4 или 6 вызовов вершинного шейдера (6 с использованием двух треугольников). Вершинный шейдер получит все активированные атрибуты, которые в вашем случае являются координатой положения и текстуры. Ничего не сделано с этими двумя значениями, но пропущено вперед в этот момент. Затем позиция автоматизирована (вам не нужен другой параметр, чтобы передать ее), но координата текстуры назначается различному свойству, которое вы назвали v_texCoord. Это означает, что координата текстуры будет интерполирована для каждого из пикселов, которые будут нарисованы, и эти значения затем будут получены в шейдере фрагмента. Именно поэтому вы можете увидеть нарисованную текстуру, поскольку каждый пиксель имеет другой цвет, полученный из текстуры с другой интерполированной координатой, полученной с помощью шейдера фрагмента. Таким образом, замена атрибута на униформу нарушит все это, интерполяции не произойдет, и все ваши пиксели будут выглядеть одинаково.

+0

Большое спасибо за этот подробный ответ – Alexanus