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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Шейдеры. Присоединение и применение.  (Прочитано 12048 раз)
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 это делается. Буду разбираться, но вопрос, пожалуй, еще открыт
« Последнее редактирование: Декабрь 14, 2014, 13:18 от JAkutenshi » Записан
JAkutenshi
Гость
« Ответ #1 : Декабрь 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();
}

Результат:


Должен быть болотный цвет по-идее.
ЧЯДНТ?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Декабрь 14, 2014, 16:06 »

Во всяком случае перепутали местами тексты вертексного и фрагментного шейдеров (это фрагментный отвечает за gl_FragColor). И сразу логи компиляции шейдеров в консоль чтобы не вслепую.

Ну и все эти игрища хороши с OpenGL 4 (на худой конец 3.2). А для более ранних карт - ой чижело  Плачущий
« Последнее редактирование: Декабрь 14, 2014, 16:15 от Igors » Записан
JAkutenshi
Гость
« Ответ #3 : Декабрь 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'"
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Декабрь 14, 2014, 17:35 »

Вопрос от отчаяния: есть шансы сделать тени через shadow map за день-полтора? ТТ
А что значит "сделать" на OpenGL? Найти пример и переписать - другого в этом царстве тупости нет. Так что все зависит от умения искать  Улыбающийся

"Поправил, но шейдер все так же не применяется. Лог пустой, в qDebug():
getProcAddress: Unable to resolve 'glProgramParameteri'
getProcAddress: Unable to resolve 'glProgramParameteriEXT'
Ну так до шейдера точно дело не дойдет. Печатайте glGetString(GL_VERSION). Может там совсем не четверка
Записан
JAkutenshi
Гость
« Ответ #5 : Декабрь 14, 2014, 17:39 »

Ну, я нашел прилично примеров, но боюсь криворучность поломает все. Впрочем, придется как-то сделать - выбора-то нет~

Там не четверка.
3.1.0 - Build 8.15.10.2345
Шейдеры же вроде после 2-го апдейта гля появились, нет?

Компилируются они кстати нормально, пишет что ошибок нет.

Перевел на основной GPU NVidia : 4.4.0 NVIDIA 344.11
« Последнее редактирование: Декабрь 14, 2014, 18:32 от JAkutenshi » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Декабрь 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
Не понял что "перевел"? Подсуньте ошибку в шейдере, должно вякнуть в логе
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #7 : Декабрь 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.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #8 : Декабрь 15, 2014, 10:10 »

У вас нет обращений к программе из метода paint. В данный момент вы рисуете с помощью OpenGL 1.x. Шейдерная программа просто болтается в памяти.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Декабрь 15, 2014, 10:59 »

У вас нет обращений к программе из метода paint. В данный момент вы рисуете с помощью OpenGL 1.x. Шейдерная программа просто болтается в памяти.
Ну тогда уже в памяти карты Улыбающийся Но я не понял - а какие обращения должны быть? Установка uniform переменных - так их пока нет. И в чем разница между рисованием 1.х и выше? По-моему так и так шейдер должен работать
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #10 : Декабрь 15, 2014, 11:07 »

glVertex3f не задействует шейдер
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #11 : Декабрь 15, 2014, 11:09 »

Вот пример простой программы на шейдерах
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #12 : Декабрь 15, 2014, 11:19 »

Во всяком случае перепутали местами тексты вертексного и фрагментного шейдеров (это фрагментный отвечает за gl_FragColor). И сразу логи компиляции шейдеров в консоль чтобы не вслепую.
Ой, да. Не сразу заметил. Присоединяюсь.
Вообще, при компиляции в stderr должна была высыпаться ошибка (В QtCreator 3 вкладка "Вывод приложения").
На википедии написано, что
Цитировать
ftransform() больше не поддерживается GLSL с версии 1.40 и GLSL ES с версии 1.0. Теперь программисты должны управлять матрицами проекции и трансформации модели в соответствии со стандартом OpenGL 3.1.
ссылка
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Декабрь 15, 2014, 11:35 »

glVertex3f не задействует шейдер
Чего это? По-моему у меня работает (кстати в том самом случае - не нашел лучшего способа вывода с фейсетными нормалями). glVertex3f - это всего лишь способ передачи данных (пусть устаревший)

Вот пример простой программы на шейдерах
Ага, версия 4.2 - и вот она, "простота" Улыбающийся А остальные "идут лесом" (в терминах молодежи) или как?
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #14 : Декабрь 15, 2014, 12:05 »

glVertex3f - это всего лишь способ передачи данных (пусть устаревший)
Да, проверил - работает. Ошибался. При неиспользовании шейдерной программы рисует белым. Так что, автор, проблема в нескомпилированной программе, точнее в перепутанных типах шейдеров.
Ага, версия 4.2 - и вот она, "простота" Улыбающийся А остальные "идут лесом" (в терминах молодежи) или как?
Версию можно затереть и точка будет рисоваться.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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