Название: Шейдеры. Присоединение и применение.
Отправлено: JAkutenshi от Декабрь 14, 2014, 13:13
Доброго времени суток. Материала много на тему шейдеров и их подключения, но либо не работает ибо пример старый, либо в упор не могу найти ответа на вопрос (смотрел пример Cube и где написано присоединение и компиляция шейдера - никак не пойму ТТ). Впрочем, был найден один вполне рабочий пример, но, хм, шейдер-то там не работает, хотя. кажется, компилируется. Итак: GLWidget.h #ifndef GLWIDGET_H #define GLWIDGET_H
#include <QGLWidget> #include <QGLShaderProgram>
class GLWidget : public QGLWidget { Q_OBJECT
float cameraX; float cameraY; float cameraZ;
float alpha; float theta;
float pressX; float pressY;
float cameraDistance;
QGLShaderProgram *shaderProgram; public: explicit GLWidget(QWidget *parent = 0);
void initializeGL(); void resizeGL(int w, int h); void paintGL();
void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event);
void initShaders(); signals:
public slots:
};
#endif // GLWIDGET_H
GLWidget.ccp #include "glwidget.h" #include <GL/glu.h> #include <QWheelEvent> #include <QMouseEvent> #include <QDebug> #include <QFileInfo> #include <qmath.h> #include "teapot.h" #include <QOpenGLVertexArrayObject>
GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) { shaderProgram = new QGLShaderProgram( this );
cameraDistance = 10; cameraX = 0; cameraY = 0; cameraZ = cameraDistance;
alpha = M_PI / 6; theta = M_PI / 6; }
void GLWidget::initializeGL() { glClearColor(0, 0, 0, 1); initShaders(); }
void GLWidget::resizeGL(int w, int h) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-w/2, w/2, -h/2, h/2, -w, w); glViewport(0, 0, w, h); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }
void GLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90, 1, 0.01, height()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glEnable(GL_CULL_FACE); glClearDepth(1.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL);
float x = cameraDistance * cos(alpha) * sin(theta); float y = cameraDistance * sin(alpha); float z = cameraDistance * cos(alpha) * cos(theta); gluLookAt(x, y, z, 0, 0, 0, 0, 1, 0);
/*GLUquadricObj *quadric = gluNewQuadric(); glColor4ub (176, 50, 153, 115); gluQuadricDrawStyle(quadric, (GLenum)GLU_SMOOTH); gluSphere(quadric, 1, 40, 40); glTranslatef(0, -1, 0);*/ drawingTeapot();
//рисуем статичные оси координат glBegin(GL_LINES); glColor3ub(255, 255, 255); glVertex3f(-300, 0, 0); glVertex3f(300, 0, 0); glVertex3f(0, -300, 0); glVertex3f(0, 300, 0); glVertex3f(0, 0, -300); glVertex3f(0, 0, 300); glEnd(); //подписи к ним renderText(270, 0, 0, "X"); renderText(0, 270, 0, "Y"); renderText(0, 0, 270, "Z"); //стол glBegin(GL_TRIANGLE_STRIP); glColor3ub(167, 58, 13); glVertex3f(10, 0, 10); glVertex3f(10, 0, -10); glVertex3f(-10, 0, 10); glVertex3f(-10, 0, -10); glEnd();
glFlush(); }
void GLWidget::wheelEvent(QWheelEvent *event) { int d = cameraDistance - (event->delta()) / 120; if (d > 1) { cameraDistance = d; updateGL(); } }
void GLWidget::mousePressEvent(QMouseEvent *event) { pressX = event->x(); pressY = event->y(); }
void GLWidget::mouseMoveEvent(QMouseEvent *event) { if (pressY - event->y() > 0) {if (alpha + 0.01 < M_PI / 2) { alpha += 0.01; } } else if (pressY - event->y() < 0) { if ( -M_PI / 2 < alpha - 0.01) { alpha -= 0.01; } } if (pressX - event->x() > 0) { theta += 0.01; } else if (pressX - event->x() < 0) { theta -= 0.01; }
int x = cameraDistance * cos(alpha) * sin(theta); int y = cameraDistance * sin(alpha); int z = cameraDistance * cos(alpha) * cos(theta);
pressX = event->x(); pressY = event->y(); updateGL(); }
void GLWidget::initShaders() {
// Compile vertex shader shaderProgram->addShaderFromSourceFile( QGLShader::Vertex, ":/vShader.vsh" );
// Compile fragment shader shaderProgram->addShaderFromSourceFile( QGLShader::Fragment, ":/fShader.fsh" );
/* // Compile vertex shader shaderProgram->addShaderFromSourceFile( QGLShader::Vertex, ":/vShader.glsl" );
// Compile fragment shader shaderProgram->addShaderFromSourceFile( QGLShader::Fragment, ":/fShader.glsl" ); */ // Bind vertex array object QOpenGLVertexArrayObject *vao = new QOpenGLVertexArrayObject( this ); vao->bind();
// Bind shader pipeline for use shaderProgram->link(); shaderProgram->bind(); }
Прошу помощи, как правильно загружать и применять шейдерные программы в Qt? Что не так в моем коде (uniform не используется, пока что шейдер примитивный на установку цвета)? Если есть пример как правильно написать это - можно? Я просмотрел прилично материала, но далеко не все оказалось подходящим. Спасибо! P.S. Хм, таки нашел где в Cube это делается. Буду разбираться, но вопрос, пожалуй, еще открыт
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: JAkutenshi от Декабрь 14, 2014, 13:47
Все-таки никак. Делаю по примеру, шейдер не применяется. #include "glwidget.h" #include <GL/glu.h> #include <QWheelEvent> #include <QMouseEvent> #include <QDebug> #include <QFileInfo> #include <qmath.h> #include "teapot.h" #include <QOpenGLVertexArrayObject>
GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent) { shaderProgram = new QGLShaderProgram( this );
cameraDistance = 10; cameraX = 0; cameraY = 0; cameraZ = cameraDistance;
alpha = M_PI / 6; theta = M_PI / 6; }
void GLWidget::initializeGL() { glClearColor(0, 0, 0, 1); initShaders(); }
void GLWidget::resizeGL(int w, int h) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-w/2, w/2, -h/2, h/2, -w, w); glViewport(0, 0, w, h); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); }
void GLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90, 1, 0.01, height()); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glEnable(GL_CULL_FACE); glClearDepth(1.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL);
float x = cameraDistance * cos(alpha) * sin(theta); float y = cameraDistance * sin(alpha); float z = cameraDistance * cos(alpha) * cos(theta); gluLookAt(x, y, z, 0, 0, 0, 0, 1, 0);
/*GLUquadricObj *quadric = gluNewQuadric(); glColor4ub (176, 50, 153, 115); gluQuadricDrawStyle(quadric, (GLenum)GLU_SMOOTH); gluSphere(quadric, 1, 40, 40); glTranslatef(0, -1, 0);*/ //drawingTeapot();
//рисуем статичные оси координат glBegin(GL_LINES); //glColor3ub(255, 255, 255); glVertex3f(-300, 0, 0); glVertex3f(300, 0, 0); glVertex3f(0, -300, 0); glVertex3f(0, 300, 0); glVertex3f(0, 0, -300); glVertex3f(0, 0, 300); glEnd(); //подписи к ним renderText(270, 0, 0, "X"); renderText(0, 270, 0, "Y"); renderText(0, 0, 270, "Z"); //стол glBegin(GL_TRIANGLE_STRIP); //glColor3ub(167, 58, 13); glVertex3f(10, 0, 10); glVertex3f(10, 0, -10); glVertex3f(-10, 0, 10); glVertex3f(-10, 0, -10); glEnd();
glFlush(); }
void GLWidget::wheelEvent(QWheelEvent *event) { int d = cameraDistance - (event->delta()) / 120; if (d > 1) { cameraDistance = d; updateGL(); } }
void GLWidget::mousePressEvent(QMouseEvent *event) { pressX = event->x(); pressY = event->y(); }
void GLWidget::mouseMoveEvent(QMouseEvent *event) { if (pressY - event->y() > 0) {if (alpha + 0.01 < M_PI / 2) { alpha += 0.01; } } else if (pressY - event->y() < 0) { if ( -M_PI / 2 < alpha - 0.01) { alpha -= 0.01; } } if (pressX - event->x() > 0) { theta += 0.01; } else if (pressX - event->x() < 0) { theta -= 0.01; }
int x = cameraDistance * cos(alpha) * sin(theta); int y = cameraDistance * sin(alpha); int z = cameraDistance * cos(alpha) * cos(theta);
pressX = event->x(); pressY = event->y(); updateGL(); }
void GLWidget::initShaders() { /* // Compile vertex shader shaderProgram->addShaderFromSourceFile( QGLShader::Vertex, ":/vShader.vsh" );
// Compile fragment shader shaderProgram->addShaderFromSourceFile( QGLShader::Fragment, ":/fShader.fsh" );
// Compile vertex shader shaderProgram->addShaderFromSourceFile( QGLShader::Vertex, ":/vShader.glsl" );
// Compile fragment shader shaderProgram->addShaderFromSourceFile( QGLShader::Fragment, ":/fShader.glsl" );
// Bind vertex array object QOpenGLVertexArrayObject *vao = new QOpenGLVertexArrayObject( this ); vao->bind();
// Bind shader pipeline for use shaderProgram->link(); shaderProgram->bind(); */
/*// Compile vertex shader if (!shaderProgram->addShaderFromSourceFile(QGLShader::Vertex, ":/vShader.glsl")) close();
// Compile fragment shader if (!shaderProgram->addShaderFromSourceFile(QGLShader::Fragment, ":/fShader.glsl")) close();
*/
if (!shaderProgram->addShaderFromSourceCode(QGLShader::Vertex, "void main(void)\n" "{gl_FragColor = vec4(0.4, 0.5, 0, 1);}")) close();
// Compile fragment shader if (!shaderProgram->addShaderFromSourceCode(QGLShader::Fragment, "void main(void)\n" "{gl_Position = ftransform();}")) close();
// Link shader pipeline if (!shaderProgram->link()) close();
// Bind shader pipeline for use if (!shaderProgram->bind()) close(); } Результат: (https://pp.vk.me/c623825/v623825266/eb8f/0D2gGPtJ0OM.jpg) Должен быть болотный цвет по-идее. ЧЯДНТ?
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: Igors от Декабрь 14, 2014, 16:06
Во всяком случае перепутали местами тексты вертексного и фрагментного шейдеров (это фрагментный отвечает за gl_FragColor). И сразу логи компиляции шейдеров в консоль чтобы не вслепую.
Ну и все эти игрища хороши с OpenGL 4 (на худой конец 3.2). А для более ранних карт - ой чижело :'(
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: JAkutenshi от Декабрь 14, 2014, 16:25
Да, на геймдеве уже поправили, стыдно за ляп - недосмотрел. Но сути не поменяло, шейдер не грузит.
Вопрос от отчаяния: есть шансы сделать тени через shadow map за день-полтора? ТТ
"Поправил, но шейдер все так же не применяется. Лог пустой, в qDebug(): getProcAddress: Unable to resolve 'glProgramParameteri' getProcAddress: Unable to resolve 'glProgramParameteriEXT' "" <- log(); getProcAddress: Unable to resolve 'glProgramParameteri' getProcAddress: Unable to resolve 'glProgramParameteriEXT' getProcAddress: Unable to resolve 'glProgramParameteri' getProcAddress: Unable to resolve 'glProgramParameteriEXT' getProcAddress: Unable to resolve 'glProgramParameteri' getProcAddress: Unable to resolve 'glProgramParameteriEXT'"
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: Igors от Декабрь 14, 2014, 17:35
Вопрос от отчаяния: есть шансы сделать тени через shadow map за день-полтора? ТТ
А что значит "сделать" на OpenGL? Найти пример и переписать - другого в этом царстве тупости нет. Так что все зависит от умения искать :) "Поправил, но шейдер все так же не применяется. Лог пустой, в qDebug(): getProcAddress: Unable to resolve 'glProgramParameteri' getProcAddress: Unable to resolve 'glProgramParameteriEXT'
Ну так до шейдера точно дело не дойдет. Печатайте glGetString(GL_VERSION). Может там совсем не четверка
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: JAkutenshi от Декабрь 14, 2014, 17:39
Ну, я нашел прилично примеров, но боюсь криворучность поломает все. Впрочем, придется как-то сделать - выбора-то нет~
Там не четверка. 3.1.0 - Build 8.15.10.2345 Шейдеры же вроде после 2-го апдейта гля появились, нет?
Компилируются они кстати нормально, пишет что ошибок нет.
Перевел на основной GPU NVidia : 4.4.0 NVIDIA 344.11
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: Igors от Декабрь 15, 2014, 09:56
Там не четверка. 3.1.0 - Build 8.15.10.2345 Шейдеры же вроде после 2-го апдейта гля появились, нет?
Не знаю истории, но на старенькой карте с OpenGL 2.1 по крайней мере вертексный и фрагментный шейдеры у меня ходят. Хотя нет многих новых возможностей. Если не ошибаюсь glPrоgramParameter требует 4 или даже чуть выше. И ftransform тоже проверьте на совместимость. В общем спецификации никто не отменял. Распечатайте QGLFormat к чему там он присосался. Ну и Qt лучше ставить "десктопный OpenGL" чтобы не упираться в ES и.т.п. Компилируются они кстати нормально, пишет что ошибок нет.
Перевел на основной GPU NVidia : 4.4.0 NVIDIA 344.11
Не понял что "перевел"? Подсуньте ошибку в шейдере, должно вякнуть в логе
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: __Heaven__ от Декабрь 15, 2014, 09:58
void GLWidget::initShaders() { /* // Compile vertex shader shaderProgram->addShaderFromSourceFile( QGLShader::Vertex, ":/vShader.vsh" );
// Compile fragment shader shaderProgram->addShaderFromSourceFile( QGLShader::Fragment, ":/fShader.fsh" );
// Compile vertex shader shaderProgram->addShaderFromSourceFile( QGLShader::Vertex, ":/vShader.glsl" );
// Compile fragment shader shaderProgram->addShaderFromSourceFile( QGLShader::Fragment, ":/fShader.glsl" );
// Bind vertex array object QOpenGLVertexArrayObject *vao = new QOpenGLVertexArrayObject( this ); vao->bind();
// Bind shader pipeline for use shaderProgram->link(); shaderProgram->bind(); */
/*// Compile vertex shader if (!shaderProgram->addShaderFromSourceFile(QGLShader::Vertex, ":/vShader.glsl")) close();
// Compile fragment shader if (!shaderProgram->addShaderFromSourceFile(QGLShader::Fragment, ":/fShader.glsl")) close();
*/
if (!shaderProgram->addShaderFromSourceCode(QGLShader::Vertex, "void main(void)\n" "{gl_FragColor = vec4(0.4, 0.5, 0, 1);}")) close();
// Compile fragment shader if (!shaderProgram->addShaderFromSourceCode(QGLShader::Fragment, "void main(void)\n" "{gl_Position = ftransform();}")) close();
// Link shader pipeline if (!shaderProgram->link()) close();
// Bind shader pipeline for use if (!shaderProgram->bind()) close(); } Здесь явно что-то лишнее. К программе подключается по одному шейдеру каждого типа, в вашем случае вершинный и фрагментный. Далее программа линкуется и прикручивается к контексту (bind). У вас же по 2 раза шейдер добавили, слинковали прикрутили, снова 2 раза добавили, снова слинковали и т.д. Попробуйте в текст шейдеров добавить ещё директиву #version 130.
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: __Heaven__ от Декабрь 15, 2014, 10:10
У вас нет обращений к программе из метода paint. В данный момент вы рисуете с помощью OpenGL 1.x. Шейдерная программа просто болтается в памяти.
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: Igors от Декабрь 15, 2014, 10:59
У вас нет обращений к программе из метода paint. В данный момент вы рисуете с помощью OpenGL 1.x. Шейдерная программа просто болтается в памяти.
Ну тогда уже в памяти карты :) Но я не понял - а какие обращения должны быть? Установка uniform переменных - так их пока нет. И в чем разница между рисованием 1.х и выше? По-моему так и так шейдер должен работать
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: __Heaven__ от Декабрь 15, 2014, 11:07
glVertex3f не задействует шейдер
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: __Heaven__ от Декабрь 15, 2014, 11:09
Вот пример (http://www.prog.org.ru/index.php?topic=27475.msg199283#msg199283)простой программы на шейдерах
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: __Heaven__ от Декабрь 15, 2014, 11:19
Во всяком случае перепутали местами тексты вертексного и фрагментного шейдеров (это фрагментный отвечает за gl_FragColor). И сразу логи компиляции шейдеров в консоль чтобы не вслепую.
Ой, да. Не сразу заметил. Присоединяюсь. Вообще, при компиляции в stderr должна была высыпаться ошибка (В QtCreator 3 вкладка "Вывод приложения"). На википедии написано, что ftransform() больше не поддерживается GLSL с версии 1.40 и GLSL ES с версии 1.0. Теперь программисты должны управлять матрицами проекции и трансформации модели в соответствии со стандартом OpenGL 3.1. ссылка (https://ru.wikipedia.org/w/index.php?title=OpenGL_Shading_Language)
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: Igors от Декабрь 15, 2014, 11:35
glVertex3f не задействует шейдер
Чего это? По-моему у меня работает (кстати в том самом случае - не нашел лучшего способа вывода с фейсетными нормалями). glVertex3f - это всего лишь способ передачи данных (пусть устаревший) Вот пример (http://www.prog.org.ru/index.php?topic=27475.msg199283#msg199283)простой программы на шейдерах
Ага, версия 4.2 - и вот она, "простота" :) А остальные "идут лесом" (в терминах молодежи) или как?
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: __Heaven__ от Декабрь 15, 2014, 12:05
glVertex3f - это всего лишь способ передачи данных (пусть устаревший)
Да, проверил - работает. Ошибался. При неиспользовании шейдерной программы рисует белым. Так что, автор, проблема в нескомпилированной программе, точнее в перепутанных типах шейдеров. Ага, версия 4.2 - и вот она, "простота" :) А остальные "идут лесом" (в терминах молодежи) или как? Версию можно затереть и точка будет рисоваться.
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: JAkutenshi от Декабрь 15, 2014, 14:35
Так, вчера был интересный в плане внезапных проблем и бесполезный в плане написанного полезного кода. Итак, тема моя на геймдеве, с обсуждением: http://www.gamedev.ru/code/forum/?id=196175
Если в кратком содержании прошедшей серии: Простейший шейдер на изменение цвета в некий статичный вектор цвета в нем. Все просто. Но он не применялся. Все компилируется, ошибок нет, все радостно, но шейдер не работает. Уважаемый форумчанин с геймдева Blew_zc собрал бинарник и передал его вместе с проектом. Какого было мое удивление, когда собранная программа рисовала нужное, а собранный проект на моей машине (по факту на моем Qt5.3, против его Qt4.6) снова не применяет шейдер! Выше описанный человек помог разобраться с причиной сей "магии": "В общем, renderText вызывает unbind шейдера (или bind какого-то своего, сейчас влом разбираться), так что вызов shaderProgram->bind() перед отрисовкой координатных осей и плоскости помог :) "
Или как вариант убрать надписи. Такие дела. Мораль? "на фреймворк надейся, а сам не плошай. "
Всем спасибо, особенно, еще раз, Blew_zc, надеюсь, если у кого-то будет эта проблема, найдет свой ответ здесь.
Название: Re: Шейдеры. Присоединение и применение.
Отправлено: 8Observer8 от Декабрь 15, 2014, 23:35
Возможно вам будет интересен мой пример (http://www.cyberforum.ru/opengl/thread1316232-page3.html#post6991000) с применением шейдеров
|