Як працюють багатопрохідні шейдери у OpenGL?


13

У Direct3D багатопрохідні шейдери прості у використанні, оскільки ви можете буквально визначати проходи в межах програми. У OpenGL це здається трохи складнішим, тому що можна надати програмі шейдерів стільки вершин, геометрії та фрагментів шейдерів, скільки вам потрібно.

Популярний приклад багатопрохідного шейдера - тоновий шейдер. Один прохід робить фактичний ефект затінення, а інший створює контур. Якщо у мене є два вершинні шейдери, "cel.vert" і "outline.vert", і два шейдери для фрагментів, "cel.frag" і "outline.frag" (подібно до того, як ви це робите в HLSL), як я можу це зробити комбінувати їх для створення повного тонового шейдера?

Я не хочу, щоб ви казали, що для цього може використовуватися шейдер геометрії, тому що я просто хочу знати теорію, що стоїть за багатопрохідними шейдерами GLSL;)


"У Direct3D багатопрохідні шейдери прості у використанні, оскільки ви можете буквально визначати проходи в межах програми." Ні, ти не можеш. Ви можете визначити проходи у файлі FX, але це не те саме, що шейдер HLSL.
Нікол Болас

Відповіді:


11

Не існує «теорії» за багатопрохідним. Немає «багатопрохідних шейдерів». Мультипас дуже простий: ви малюєте об’єкт за допомогою однієї програми. Потім ви малюєте об’єкт за допомогою іншої програми.

Ви можете використовувати такі елементи D3DX, як файли FX, щоб приховати ці додаткові пропуски. Але вони все одно працюють так. OpenGL просто не має для цього сховку.


1

Візуалізуйте об'єкт за допомогою шейдера для комірок, а потім знову відтворіть його за допомогою шейдера для контуру.


1
Тож я повинен зробити дві різні програми шейдерів? Чому саме тоді я можу надати програмі шейдера стільки вершин / геометрії / фрагментів шейдерів, скільки я хочу? Має бути спосіб зробити це за допомогою однієї програми.
jmegaffin

1
Ви не надаєте йому шейдери для декількох вершин (тощо). Є лише одна основна функція, тому у вас немає декількох точок входу. Він дуже схожий на програму C тим, що ви можете мати декілька файлів, які пов'язані між собою для створення програми. Ви можете ділитися цими файлами між різними програмами, щоб не потрібно дублювати код, але кожен файл не обов'язково є програмою сам по собі.
Chewy Gumball

1
Ось так і слід: Візуалізуйте один раз однією шейдерною парою (вершина + фрагмент), а потім знову з іншою парою (або використовуйте ту саму вершину шейдера + інший шейдер фрагмента). Іноді ви візуалізуєте в буфер і використовуєте (ще) інший шейдер, щоб "змішати" його з кінцевим результатом.
Валмонд

1

У OpenGL 4.0 є рівномірні підпрограми . Вони дозволяють визначати функції, які можна замінити під час виконання з дуже невеликими накладними витратами. Таким чином, ви можете зробити 1 функцію за кожен прохід. Також 1 функція для кожного типу шейдерів.

Тут є підручник .

Для старих версій OpenGL найкраще скористатися купою різних шейдерів і обмінятися між ними. В іншому випадку ви можете скласти значення, які ви помножите на рівномірне значення, яке становить 0,0 або 1,0, щоб увімкнути або вимкнути його. Інакше умовно, якщо можна використовувати оператори, але OpenGL виконує всі можливі результати при кожному виконанні / проходженні, тому переконайтеся, що вони не надто важкі.


0

Є деякі люди, які знають багато про GLSL, тому я сподіваюся, що вони встановили рекорди прямо, але виходячи з того, що я бачив, ви повинні мати можливість у вашому шейдері фрагментів зробити щось подібне (псевдокод, я Фактичний GLSL залиште людям, які це краще знають):

out vec4 fragment_color
vec4 final_color
final_color = flat_color
If this fragment is in shadow
    final_color = shadow_color
If this fragment is an edge
    final_color = edge_color
If this fragment is a highlight
    final_color = highlight_color
fragment_color = final_color

Використовуючи ifs таким чином, ви отримуєте щось на зразок декількох проходів. Чи має це сенс?

Редагувати: Також, сподіваємось, це запитання щодо ТА допомагає усунути деякі непорозуміння.


2
Важливо зазначити, що GLSL буде виконувати всі оператори у гілках if, якщо вони проходять, навіть якщо вони не ввімкнено. Мабуть, просто обчислити все і додати всі кольори разом, але помножити значення на 1,0 або 0,0, щоб увімкнути або вимкнути їх швидше.
Давид К. Єпископ

1
@ DavidC.Bishop: Це неправда. Принаймні, не гарантовано правда. Компілятор вирішить, чи дійсна гілка швидша, або швидше "обчислити все і розібрати".
Нікол Болас

1
Крім того, поведінка, на яку посилається @ DavidC.Bishop, навряд чи характерна для шейдерів та GPU. Сучасні процесори, що виконують звичайні програми, спекулятивно виконують принаймні одну з гілок, якщо перевірене значення ще не доступне. Якщо вони виявляються помилковими, вони відкочуються і повторюються. Це в кінцевому підсумку дає велику швидкість в середньому.
ipeet
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.