Russian Qt Forum
Ноябрь 22, 2024, 04:12 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Помогите разобраться с шейдерами  (Прочитано 23126 раз)
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« : Ноябрь 15, 2017, 16:54 »

Начал разбираться с шейдерами. Возникло несколько вопросов.

Правильно ли я понимаю, что вершинный шейдер существует в единственном числе, обязательно применяется ко всем вершинам?

Можно ли для разных вершин сделать разные шейдеры?

Как Qt может помочь с путаницей в синтаксисе GLSL в разных версиях OpenGL?
А я пишу программу на Qt 4.6. А там согласно документации в QGLContext нет функции setVersion, введённой в Qt 4.7: http://doc.qt.io/qt-5/qglformat.html#setVersion
Нет ли другого способа выставить версию OpenGL?
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #1 : Ноябрь 16, 2017, 09:24 »

Можно использовать несколько вершинных шейдеров и линковать их с одним и тем же (или разными) фрагментным шейдером. Таким образом получается шейдерная программа. Имея набор шейдерных программ (а может и не набор, а всего 1 программу) можно с их помощью рисовать примитивы с помощью вершин, которые подаются для отрисовки. Например, мы можем прикрутить (bind) шейдерную программу 1 и вызвать функцию рисования квадратов, которые формируют куб постоянного цвета (который задаётся с помощью uniform), а затем прикрутить шейдерную программу 2 и нарисовать с её помощью сферу с переливающимися цветами (тут уже атрибутом задаётся цвет каждой вершины).

Цитировать
Как Qt может помочь с путаницей в синтаксисе GLSL в разных версиях OpenGL?
Вроде, никак.

Цитировать
нет функции setVersion
Пользуюсь Qt 5. Ниразу не вызывал эту функцию. В основном задаю в коде шейдера
Код:
#version 130
Насчёт правильности моих действий не уверен, но это работает.
Наверное, setVersion не позволяет вызывать gl функции старших версий opengl.

Есть тема с выполнением примеров из SuperBible на Qt5 и шейдерах. Возможно, будет полезной.
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #2 : Ноябрь 16, 2017, 17:28 »

Что не так в этих шейдерах? Компиляция проходит, линк ошибка. Версия согласно glGetString ( GL_SHADING_LANGUAGE_VERSION ) 1.2
Можно ли поднять версию, чтоб хотя бы были in и out переменные, или это от железа зависит?

Код
C++ (Qt)
void compileShader()
{
_shader = new QGLShaderProgram();
_shader->addShaderFromSourceCode(QGLShader::Vertex,
"//#version 120\n"
"varying highp vec4 _color;\n"
"void main(void)\n"
"{\n"
"     _color = (length(gl_Position) < 90 && length(gl_Position)>80) ? vec4(1,0,0,1) : gl_Color;\n"
"}");
_shader->addShaderFromSourceCode(QGLShader::Fragment,
"//#version 120\n"
"varying highp vec4 _color;\n"
"void main(void)\n"
"{\n"
"   gl_FragColor = _color;\n"
"}");
_shader->link();
}

Как я понял, шейдер должен вернуть gl_Position.
А что мне делать, если я хочу использовать позицию вершины, вычисленную как если бы не было никакого шейдера?
Как в коде и написано. Нет ли специальной встроенной переменной?
« Последнее редактирование: Ноябрь 16, 2017, 17:55 от qtkoder777 » Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #3 : Ноябрь 17, 2017, 09:47 »

Кажется, обычно записывают в gl_Position преобразованную вершину с помощью матриц проекции и представления. Далее она будет помножена на матрицу вьюпорта (если не произойдёт её отсечение при наличии координаты по модулю, превышающей 1.0f), что преобразует её в экранную координату.
Тут пример того, как это преобразование происходит.

Цитировать
А что мне делать, если я хочу использовать позицию вершины, вычисленную как если бы не было никакого шейдера?
Для каждой вершины задавать атрибут цвета, который должен поставляться к каждой вершине.

Цитировать
Можно ли поднять версию, чтоб хотя бы были in и out переменные, или это от железа зависит?
Да, in out зависят от версии, а версия может не всеми железками поддерживаться. Попробуйте поднять. Если нет поддержки железом, то в консоль программы выведется ошибка компиляции шейдера.

Цитировать
Компиляция проходит, линк ошибка
Было бы неплохо приводить лог ошибки.

Для упрощения себе жизни можете писать шейдеры в отдельных файлах, которые хранятся в ресурсах, а на компиляцию подавать их с помощью
bool QGLShader::compileSourceFile ( const QString & fileName )
« Последнее редактирование: Ноябрь 17, 2017, 09:52 от __Heaven__ » Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #4 : Ноябрь 17, 2017, 12:02 »

Ошибка была из-за отсутствия записи в gl_Position в вершинном шейдере.

В первых версиях OpenGL есть функции glRotate и т.д, избавляющие программиста от работы с матрицами, множество удобных функций в glu и glut. Теперь всё объявлено deprecated, надо писать свои матрицы, рисовать массивами вместо glVertex, что снижает читаемость кода и требует написания обёрток, возвращающих старую функциональность. Так можно до ассемблера опуститься. К чему идёт дело?
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #5 : Ноябрь 17, 2017, 12:53 »

Есть же QMatrix4x4 с методами rotate. Множество удобных функций glu и glut есть и в qt. Рисовать массивами быстрее, чем по одной вершине передавать в gpu. Да и объект ваш наверняка есть набор вершин. Грамотно составив архитектуру вы получите вполне читаемый код.
Более того, вроде, все перечисленные здесь deprecated функции никто не запрещает использовать по сей день.
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #6 : Ноябрь 17, 2017, 14:08 »

Зачем делать "правильным" рисование массивами, всё равно не понимаю. Внутри библиотеки можно сделать так

glBegin - начали формировать массив
glVertex - пишем в массив вершину
glEnd - кончили формировать массив
передали массив в GPU

Код остался в старом стиле.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #7 : Ноябрь 17, 2017, 14:24 »

Правильным считается не передавать данные на видеоадаптеру каждый раз при отрисовке (так как это достаточно накладно при большом объеме данных), а формировать массивы сразу на стороне видеоадаптера в виде массивов и вызывать методы видеоадаптера для их обработки.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #8 : Ноябрь 17, 2017, 14:30 »

glBegin - начали формировать массив
glVertex - пишем в массив вершину
glEnd - кончили формировать массив
Что мешает сейчас так писать?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Ноябрь 19, 2017, 12:16 »

Как я понял, шейдер должен вернуть gl_Position.
А что мне делать, если я хочу использовать позицию вершины, вычисленную как если бы не было никакого шейдера?
Рисуются (рендеятся) не вертексы сами по себе, а примитивы, часто говорят "фейсы", это общее название как для полигонов, так и для точек и линий. Тип примитива обязательно указывается, см напр аргумент glBegin

Если Вы хотите что-то порисовать "как на плоскости", то нужно вывести пр-к (хотя бы с помощью того же glBegn/glEnd) так чтобы он покрывал весь экран (см glOrtho). В вертексном шейдере сделать стандартное умножение на матрицу MVP  (это есть в любом примере), а цветом заниматься уже в фрагментном. Или можно задать цвет в каждом вертексе и передать его в фрагментный с помощью varying

[off]
Правильным считается не передавать данные на видеоадаптеру каждый раз при отрисовке (так как это достаточно накладно при большом объеме данных), а формировать массивы сразу на стороне видеоадаптера в виде массивов и вызывать методы видеоадаптера для их обработки.
Ну что же Вы "великий GPU" опустили до "видеадаптера"?  Улыбающийся Хотя конечно правильно, железяка и есть железяка [off]
Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #10 : Ноябрь 20, 2017, 14:21 »

А где можно прочитать хорошее описание всех встроенных переменных GLSL?
В спецификации есть только список переменных, но из названия переменной не всегда очевидно ее назначение.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #11 : Ноябрь 20, 2017, 14:41 »

https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL)
« Последнее редактирование: Ноябрь 20, 2017, 21:02 от gil9red » Записан
qtkoder777
Частый гость
***
Offline Offline

Сообщений: 245


Просмотр профиля
« Ответ #12 : Ноябрь 23, 2017, 13:26 »

Вот чем руководствовались разработчики Qt когда сделали конструктор QMatrix4x4(qreal*) с вектором, в котором матрица расположена по строкам, в то время как в OpenGL она располагается по столбцам. Ведь и в Qt5 это осталось
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #13 : Ноябрь 23, 2017, 13:44 »

Вот чем руководствовались разработчики Qt когда сделали конструктор QMatrix4x4(qreal*) с вектором, в котором матрица расположена по строкам, в то время как в OpenGL она располагается по столбцам.

Чтобы жизнь мёдом не казалась Улыбающийся. Вроде в OpenGL матрица не обязательно по столбцам располагается должна: 9.005 Are OpenGL matrices column-major or row-major?. Важнее, чтобы в нужных местах одинаково было.
Записан

Пока сам не сделаешь...
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #14 : Ноябрь 23, 2017, 14:45 »

Думаю, это связано с тем, что человек обычно читает слева-направо и сверху-вниз Улыбающийся
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.198 секунд. Запросов: 23.