Russian Qt Forum

Qt => OpenGL => Тема начата: qtkoder777 от Ноябрь 15, 2017, 16:54



Название: Помогите разобраться с шейдерами
Отправлено: qtkoder777 от Ноябрь 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?


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

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

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

Есть тема (http://www.prog.org.ru/topic_27475_0.html) с выполнением примеров из SuperBible на Qt5 и шейдерах. Возможно, будет полезной.


Название: Re: Помогите разобраться с шейдерами
Отправлено: qtkoder777 от Ноябрь 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.
А что мне делать, если я хочу использовать позицию вершины, вычисленную как если бы не было никакого шейдера?
Как в коде и написано. Нет ли специальной встроенной переменной?


Название: Re: Помогите разобраться с шейдерами
Отправлено: __Heaven__ от Ноябрь 17, 2017, 09:47
Кажется, обычно записывают в gl_Position преобразованную вершину с помощью матриц проекции и представления. Далее она будет помножена на матрицу вьюпорта (если не произойдёт её отсечение при наличии координаты по модулю, превышающей 1.0f), что преобразует её в экранную координату.
Тут (http://www.prog.org.ru/index.php?topic=27475.msg199778#msg199778) пример того, как это преобразование происходит.

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

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

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

Для упрощения себе жизни можете писать шейдеры в отдельных файлах, которые хранятся в ресурсах, а на компиляцию подавать их с помощью
bool QGLShader::compileSourceFile ( const QString & fileName ) (https://doc.qt.io/archives/4.6/qglshader.html#compileSourceFile)


Название: Re: Помогите разобраться с шейдерами
Отправлено: qtkoder777 от Ноябрь 17, 2017, 12:02
Ошибка была из-за отсутствия записи в gl_Position в вершинном шейдере.

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


Название: Re: Помогите разобраться с шейдерами
Отправлено: __Heaven__ от Ноябрь 17, 2017, 12:53
Есть же QMatrix4x4 (https://doc.qt.io/archives/4.6/qmatrix4x4.html) с методами rotate. Множество удобных функций glu и glut есть и в qt. Рисовать массивами быстрее, чем по одной вершине передавать в gpu. Да и объект ваш наверняка есть набор вершин. Грамотно составив архитектуру вы получите вполне читаемый код.
Более того, вроде, все перечисленные здесь deprecated функции никто не запрещает использовать по сей день.


Название: Re: Помогите разобраться с шейдерами
Отправлено: qtkoder777 от Ноябрь 17, 2017, 14:08
Зачем делать "правильным" рисование массивами, всё равно не понимаю. Внутри библиотеки можно сделать так

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

Код остался в старом стиле.


Название: Re: Помогите разобраться с шейдерами
Отправлено: ssoft от Ноябрь 17, 2017, 14:24
Правильным считается не передавать данные на видеоадаптеру каждый раз при отрисовке (так как это достаточно накладно при большом объеме данных), а формировать массивы сразу на стороне видеоадаптера в виде массивов и вызывать методы видеоадаптера для их обработки.


Название: Re: Помогите разобраться с шейдерами
Отправлено: __Heaven__ от Ноябрь 17, 2017, 14:30
glBegin - начали формировать массив
glVertex - пишем в массив вершину
glEnd - кончили формировать массив
Что мешает сейчас так писать?


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

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

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


Название: Re: Помогите разобраться с шейдерами
Отправлено: qtkoder777 от Ноябрь 20, 2017, 14:21
А где можно прочитать хорошее описание всех встроенных переменных GLSL?
В спецификации есть только список переменных, но из названия переменной не всегда очевидно ее назначение.


Название: Re: Помогите разобраться с шейдерами
Отправлено: __Heaven__ от Ноябрь 20, 2017, 14:41
https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL) (https://www.khronos.org/opengl/wiki/Built-in_Variable_(GLSL))


Название: Re: Помогите разобраться с шейдерами
Отправлено: qtkoder777 от Ноябрь 23, 2017, 13:26
Вот чем руководствовались разработчики Qt когда сделали конструктор QMatrix4x4(qreal*) с вектором, в котором матрица расположена по строкам, в то время как в OpenGL она располагается по столбцам. Ведь и в Qt5 это осталось


Название: Re: Помогите разобраться с шейдерами
Отправлено: ViTech от Ноябрь 23, 2017, 13:44
Вот чем руководствовались разработчики Qt когда сделали конструктор QMatrix4x4(qreal*) с вектором, в котором матрица расположена по строкам, в то время как в OpenGL она располагается по столбцам.

Чтобы жизнь мёдом не казалась :). Вроде в OpenGL матрица не обязательно по столбцам располагается должна: 9.005 Are OpenGL matrices column-major or row-major? (https://www.opengl.org/archives/resources/faq/technical/transformations.htm). Важнее, чтобы в нужных местах одинаково было.


Название: Re: Помогите разобраться с шейдерами
Отправлено: __Heaven__ от Ноябрь 23, 2017, 14:45
Думаю, это связано с тем, что человек обычно читает слева-направо и сверху-вниз :)


Название: Re: Помогите разобраться с шейдерами
Отправлено: Igors от Ноябрь 23, 2017, 15:08
Вот чем руководствовались разработчики Qt когда сделали конструктор QMatrix4x4(qreal*) с вектором, в котором матрица расположена по строкам, в то время как в OpenGL она располагается по столбцам. Ведь и в Qt5 это осталось
Руководствовались именно совместимостью с OpenGL. Где матрицы хранятся в памяти в row-major (смещение в последней строке), но используются как column-major (смещение в последнем столбце). Др словами если Вы сделаете QMatrix4x4::setRow, то в памяти перезапишется столбец, но рез-т будет "по документации" как если бы изменили строку.

Да, извращенцы, ну что поделаешь...