2010-04-29 8 views
29

Я пытаюсь обернуть голову шейдерами в GLSL, и я нашел полезные ресурсы и учебные пособия, но я продолжаю сталкиваться с стенами для чего-то, что должно быть фундаментальным и тривиальным: как мой шейдер фрагмента извлекает цвет текущего фрагмента?Как получить текущий цвет фрагмента?

Вы установили окончательный цвет, указав gl_FragColor = whatever, но, по-видимому, это значение только для вывода. Как вы получаете исходный цвет ввода, чтобы вы могли выполнять вычисления на нем? Это должно быть где-то в переменной, но если кто-то там знает свое имя, они, похоже, не записали его ни в каком учебнике или документации, с которыми я столкнулся до сих пор, и это подталкивает меня к стене.

+0

«Оригинальный цвет ввода»: вы имеете в виду свойства материала, назначенные вашему фрагменту (текстура, diffusecolor ..)? – DamienD

ответ

14

Фрагмент шейдера принимает gl_Color и gl_SecondaryColor как атрибуты вершин. Он также получает четыре переменные: gl_FrontColor, gl_FrontSecondaryColor, gl_BackColor и gl_BackSecondaryColor, что он может писать значения. Если вы хотите передать исходные цвета прямо через, вы могли бы сделать что-то вроде:

gl_FrontColor = gl_Color; 
gl_FrontSecondaryColor = gl_SecondaryColor; 
gl_BackColor = gl_Color; 
gl_BackSecondaryColor = gl_SecondaryColor; 

Исправлена ​​функциональность в трубопроводе после вершинного шейдера будет зажать их в диапазоне [0..1], и фигуры вне зависимости от того, находится ли вершина лицевой стороной или обратная сторона. Затем он будет интерполировать выбранный (передний или задний) цвет, как обычно. Затем шейдер фрагмента получит выбранные, зажатые, интерполированные цвета как gl_Color и gl_SecondaryColor.

Например, если вы нарисовали стандартный "смерть треугольник", как:

glBegin(GL_TRIANGLES); 
    glColor3f(0.0f, 0.0f, 1.0f); 
    glVertex3f(-1.0f, 0.0f, -1.0f); 
    glColor3f(0.0f, 1.0f, 0.0f); 
    glVertex3f(1.0f, 0.0f, -1.0f); 
    glColor3f(1.0f, 0.0f, 0.0f); 
    glVertex3d(0.0, -1.0, -1.0); 
glEnd(); 

Тогда вершинный шейдер, как это:

void main(void) { 
    gl_Position = ftransform(); 
    gl_FrontColor = gl_Color; 
} 

с пиксельным шейдером, как это:

void main() { 
    gl_FragColor = gl_Color; 
} 

передаст цвета, как если бы вы использовали конвейер с фиксированной функциональностью.

+25

Большинство всего, что вы делаете, устарело после версии 120. На самом деле это не только предупреждения, но и ошибки. Также не будет работать с OpenGL ES 2.0 (также уходит в 4.x?) – user697111

3

Вся точка вашего шейдера фрагмента - это решить, каков выходной цвет. Как вы это делаете, это зависит от того, что вы пытаетесь сделать.

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

6

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

Основная причина этого заключается в том, что, возможно, во время работы вашего шейдера фрагментов пока неизвестно. Фрагментные шейдеры запускаются параллельно, потенциально (в зависимости от того, какое оборудование) влияет на один и тот же пиксель, а отдельный блок, считывающий из своего рода FIFO, обычно отвечает за объединение этих данных позже. Это слияние называется «Смешивание» и пока не является частью программируемого конвейера. Это фиксированная функция, но у нее есть несколько разных способов объединить то, что генерирует ваш шейдер фрагмента с предыдущим значением цвета пикселя.

12

Если вы хотите сделать многопроходное рендеринг, т. Е.если вы оказали на фреймбуфер и хотите на второй проход рендеринга, где вы используете предыдущую визуализацию, чем ответ:

  1. Рендер первого прохода в текстуру
  2. Bind этой текстуру для второго прохода
  3. Доступ к privously оказываемых пикселей в шейдере

шейдер код 3.2:

uniform sampler2D mytex; // texture with the previous render pass 

layout(pixel_center_integer) in vec4 gl_FragCoord; 
// will give the screen position of the current fragment 

void main() 
{ 
    // convert fragment position to integers 
    ivec2 screenpos = ivec2(gl_FragCoord.xy); 
    // look up result from previous render pass in the texture 
    vec4 color = texelFetch(mytex, screenpos, 0); 
    // now use the value from the previous render pass ... 
} 

Другими методами обработки изображенного изображения будут OpenCL с OpenGL -> OpenCL interop. Это позволяет вычислить больше процессора, чем вычисление.

4

Вы должны попробовать текстуру в текущих координатах пикселя, что-то вроде этого

vec4 pixel_color = texture2D(tex, gl_TexCoord[0].xy);

Примечания, - как я видел Texture2D осуждается в GLSL 4.00 спецификации - просто посмотрите на подобную структуру ... принести функции ,

Также иногда лучше поставить свои собственные координаты пикселей вместо gl_TexCoord [0] .xy - в этом случае запись вершинных шейдеров что-то вроде:

varying vec2 texCoord; 

void main(void) 
{ 
    gl_Position = vec4(gl_Vertex.xy, 0.0, 1.0); 
    texCoord = 0.5 * gl_Position.xy + vec2(0.5);  
}

И в использовании шейдера фрагмент этой texCoord переменной вместо gl_TexCoord [0] .xy.

Удачи.

-3

как-делать-я-получить тока цветом из-а-фрагмент

Некоторые говорят, что это не может быть сделано, но я говорю, что это работает для меня:

//Toggle blending in one sense, while always disabling it in the other. 
void enableColorPassing(BOOL enable) { 
//This will toggle blending - and what gl_FragColor is set to upon shader execution 
    enable ? glEnable(GL_BLEND) : glDisable(GL_BLEND); 
    //Tells gl - "When blending, change nothing" 
    glBlendFunc(GL_ONE, GL_ZERO); 
} 

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

Ну, по крайней мере, это работает для меня.

+5

-1: Для «это работает для меня» ерунда, даже не утруждая себя тем, что вы на самом деле используете. Кроме того, для поддержки неопределенного поведения, не беспокоясь о том, какое оборудование вы используете, что делает это. –

1

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

Обычно объекты смешиваются в том порядке, в котором они добавляются в сцену, если только они не были упорядочены с помощью z-buffering algo. Сначала вы должны добавить свои непрозрачные объекты, а затем аккуратно добавить свои прозрачные объекты в порядке их смешивания.

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

Настройка функций смешивания SRC и DST для прозрачных объектов дает вам доступ к предыдущей смеси различными способами.

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

enter image description here
Рис 1 -. Однопроходный

Если вам действительно нужно multi pass (. Рис 2), то вы должны быть направлены на фреймбуфера выходы дополнительного блока текстуры, а не на экране, а также скопируйте эту целевую текстуру на следующий проход и т. д., ориентируясь на экран в последнем проходе. Для каждого прохода требуется как минимум два контекстных переключателя.

Дополнительное копирование и переключение контекста сильно ухудшают производительность рендеринга. Обратите внимание, что многопотоковые конвейеры GPU здесь не очень помогают, так как многопроходный интерфейс по сути сериализуется.

enter image description here
Рисунок 2 -. Многопроходной

я прибег к словесному описанию с диаграммами трубопровода, чтобы избежать Deprecation, так как язык шейдеров (сленг/GLSL) может быть изменено.

Смежные вопросы