Як шейдер фрагментів знає, яку змінну використовувати для кольору пікселя?


83

Я бачу багато різних фрагментних шейдерів,

І всі вони використовують різну змінну для "кольору кольору" (у даному випадку flatColor). Тож як OpenGL знає, що ви намагаєтесь зробити?

Я здогадуюсь, що це працює, оскільки flatColorєдина змінна визначена як out, але вам дозволено додавати більше outзмінних, чи не так? Або це просто впаде?


Власне, як тест я просто провів таке:

Це добре працювало, чи використовував я xчи y.


Крім того, у нас є попередньо визначений gl_FragColor. У чому різниця, і чому люди зазвичай наполягають на використанні власних змінних?

Відповіді:


143

Крім того, у нас є заздалегідь визначений gl_FragColor.

Почнемо з цього. Ні, у вас немає попередньо визначеного gl_FragColor. Це було видалено з ядра OpenGL 3.1 і вище. Якщо ви не використовуєте сумісність (у цьому випадку ваші шейдери 3,30 повинні писати #version 330 compatibilityвгорі), ви ніколи не повинні використовувати це.

Тепер повернемося до визначених користувачем виходів шейдерів фрагментів. Але спочатку швидка аналогія.

Пам'ятайте, як у вершинних шейдерах ви маєте вхідні дані? І ці входи є вершину індексів атрибутів, число Проходьте glVertexAttribPointerі glEnableVertexAttribArrayтак далі? Ви встановлюєте, який вхід витягує з якого атрибута. У GLSL 3.30 ви використовуєте такий синтаксис:

Це встановлює введення colorвершинного шейдера з місця розташування атрибутів 2. До 3.30 (або без ARB_explicit_attrib_location) вам доведеться або налаштувати це явно, glBindAttrbLocationперед зв’язуванням, або запитати програму для індексу атрибутів glGetAttribLocation. Якщо ви явно не вказали розташування атрибута, GLSL призначить місце довільно (тобто: визначеним реалізацією способом).

Встановлення його в шейдері майже завжди є кращим варіантом.

У будь-якому випадку виходи фрагментних шейдерів працюють майже точно так само. Шейдери фрагментів можуть писати на кілька вихідних кольорів , які самі потрапляють у кілька буферів в буфері кадрів . Отже, вам потрібно вказати, який вихід надходить на який фрагмент виводить колір.

Цей процес починається зі значення розташування вихідного фрагмента. Він встановлений дуже подібно до місць введення вершинного шейдера:

Є також функції API glBindFragDataLocationта glGetFragDataLocation, які є аналогами glBindAttribLocationта glGetAttribLocation.

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

Тепер , щоб бути справедливим, ваша програма повинна не вдалося в зв'язку , коли ви використовували два виходи, які не отримують в різних місцях виходу. Напевно, сталося так, що ваш компілятор оптимізував той, який ви не записали, тому він начебто забув про нього, коли прийшов час перевірити помилки компонувальника.


4
Бажаю, щоб я міг дати більше +1. Вражаюча відповідь. Мені було цікаво, як працювали місця виведення фрагментів. :)
kevintodisco

Ааа .. отже, вони gl_FragColorвідмовили на користь надання вам більшої гнучкості у виборі, в який буфер писати? Має сенс. Знову дякую!
mpen

3
@Mark: "Знищення" означає "ви все ще можете ним користуватися, але воно може бути видалено в пізніших версіях". "Видалено" означає видалено . Різниця є. Те, що було позначено як застаріле в GL 3.0, було видалено в 3.1 (за винятком кількох речей).
Nicol Bolas

3
@NicolBolas: "GL 3.3 і вище (це зміна порівняно з попередніми версіями) призначить їх усіх до місця 0". Цікаво, де це гарантується специфікацією. 3.3 сказано: "Коли програма пов'язана, будь-які варіюючі змінні без прив'язки, зазначеної [...] або явно встановленої в тексті шейдера, автоматично будуть прив'язані до кольорів фрагментів та індексів GL. Всі такі призначення використовуватимуть кольорові індекси нуль. ". Останнє речення відсутнє в 3.2. Однак індекс відноситься не до числа кольорів, а лише до індексу змішування подвійного джерела (який було додано в 3.3).
derhass

1
Дякую @NicolBolas, чудова відповідь! Отже, я ще не повністю зрозумів це, і просто хочу зробити це «без питань». У наших шейдерах ми завжди вказуємо, layout (location = 0) out vec4 outColorколи малюємо до того, що пов'язано (найчастіше "екран", а не FBO). Отже, за замовчуванням, якщо ми не зв’язали FBO (або інший буфер) за допомогою glDrawBuffers, і ми вказали location = 0, він завжди буде правильно малювати на екрані?
AzP

10

Я хотів би вказати це для OpenGLES 3.1, який використовує посилання GLSL_ES_3.10 :

§4.4.2

Якщо є лише один вихід [у шейдері фрагментів], розташування не потрібно вказувати, і в цьому випадку за замовчуванням воно дорівнює нулю.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.