Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Qt и кроссплатформенное программирование С/С++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.03.2015, 23:41   #1
wf778899
 
Регистрация: 11.03.2015
Сообщений: 5
По умолчанию OpenGL4.3 в Qt5.4 - передача значения в uniform переменную вершинного шейдера.

Привет всем! Копаюсь с OpenGL 4.3 из-под QT5.4. Возникла проблема с передачей значения в uniform-переменную вершинного шейдера. Изначально хотел передать матрицу, поиграться с видом, но не взошло. Код ниже. Стал разбираться. Вместо матрицы просто объявил в вертексном шейдере uniform int scale. На неё умножаю выходные координаты вершины (просто чтоб было видно результат). Выяснил, что проблема - при вычислении индекса переменной шейдера (дальше, в PaintGL() - так же красным цветом). glGetUniformLocation для этой переменной возвращает -1. В чём причина? Переменная в шейдере как-то не так объявлена? Подскажите, кто знает, куда копать дальше.

Код:
void OpenGLWindow::initializeGL() {
//Здесь инициализируем рендер. Устанавливаем цвет очистки окна и текущий цвет рендера.
    funcs->glClearColor(0,0,0,1);
    funcs->glColor4f(1.0, 0.0, 0.0, 1.0);
//Здесь же создаются и компилируются 2 шейдера - Vertex-шейдер и Fragment-шейдер.
    const char *vertexShader =
            "#version 400\n"
            "in vec3 position;"
            "in vec3 color;"
            "uniform int scale;"
            "out vec3 fragmentColor;"
            "void main (void) {"
            "   gl_Position = vec4(position.x*scale, position.y*scale, position.z*scale, 1.0);"
            "   fragmentColor = color;"
            "}";
    const char *fragmentShader =
            "#version 400\n"
            "in vec3 fragmentColor;"
            "out vec4 Colour;"
            "void main()  {"
            "  Colour = vec4(fragmentColor, 1.0);"
            "}";
//Создание шейдерной программы происходит в несколько этапов:
  //Создаём Vertex-шейдер и получаем его ID (int-значение) для дальнейшей работы с ним
    vsID = funcs->glCreateShader(GL_VERTEX_SHADER);
//Указываем шейдеру его исходный код
    funcs->glShaderSource(vsID, 1, &vertexShader, NULL);
//Компилируем шейдер
    funcs->glCompileShader(vsID);
//То же самое для Fragment-шейдера
    fsID = funcs->glCreateShader(GL_FRAGMENT_SHADER);
    funcs->glShaderSource(fsID, 1, &fragmentShader, NULL);
    funcs->glCompileShader(fsID);
//Получаем отладочную информацию по компиляции (реализация ниже)
    compileReport();
}

void OpenGLWindow::paintGL() {
    GLuint shaderProgramm = funcs->glCreateProgram();
    funcs->glAttachShader(shaderProgramm, vsID);
    funcs->glAttachShader(shaderProgramm, fsID);
    funcs->glLinkProgram(shaderProgramm);

    float vertices[60] = {0.0f, 0.0f,0.0f,   0.0f,0.0f,1.0f,
                          0.0f, 1.0f,0.0f,   1.0f,0.0f,0.0f,
                          0.7f, 0.7f,0.0f,   0.0f,1.0f,0.0f,
                          1.0f, 0.0f,0.0f,   0.0f,0.0f,1.0f,
                          0.7f,-0.7f,0.0f,   1.0f,0.0f,0.0f,
                          0.0f,-1.0f,0.0f,   0.0f,1.0f,0.0f,
                         -0.7f,-0.7f,0.0f,   0.0f,0.0f,1.0f,
                         -1.0f, 0.0f,0.0f,   1.0f,0.0f,0.0f,
                         -0.7f, 0.7f,0.0f,   0.0f,0.1f,0.0f,
                          0.0f, 1.0f,0.0f,   1.0f,0.0f,0.0f};

    GLuint vboID, vaoID, positionID, colorID, scaleID;
    positionID = funcs->glGetAttribLocation(shaderProgramm, "position");
    colorID = funcs->glGetAttribLocation(shaderProgramm, "color");

    scaleID = funcs->glGetUniformLocation(shaderProgramm, "scale");
    qDebug() << positionID << "pos\n" << colorID << "col\n" << scaleID << "scale\n";

    funcs->glGenBuffers(1, &vboID);
    funcs->glBindBuffer(GL_ARRAY_BUFFER, vboID);
    funcs->glBufferData(GL_ARRAY_BUFFER, 60*sizeof(float), vertices, GL_STATIC_DRAW);
    funcs->glBindBuffer(GL_ARRAY_BUFFER, 0);

    funcs->glGenVertexArrays(1, &vaoID);
    funcs->glBindVertexArray(vaoID);
    funcs->glBindBuffer(GL_ARRAY_BUFFER, vboID);
    funcs->glVertexAttribPointer(positionID, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (const GLvoid*)0);
    funcs->glEnableVertexAttribArray(positionID);
    funcs->glVertexAttribPointer(colorID, 3, GL_FLOAT, GL_FALSE, 6*sizeof(float), (const GLvoid*)12);
    funcs->glEnableVertexAttribArray(colorID);

    funcs->glBindVertexArray(0);

    funcs->glUseProgram(shaderProgramm);
    funcs->glBindVertexArray(vaoID);
    funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 10);
    funcs->glDeleteVertexArrays(1, &vaoID);
}

Последний раз редактировалось wf778899; 18.03.2015 в 09:16.
wf778899 вне форума Ответить с цитированием
Старый 18.03.2015, 19:22   #2
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Цитата:
Изначально хотел передать матрицу, поиграться с видом, но не взошло.
Проблема в том, что вы не разобрали примеры из Qt. Первым делом эти:
C:\Qt\Qt5.4.0\Examples\Qt-5.4\opengl\hellogl2
C:\Qt\Qt5.4.0\Examples\Qt-5.4\opengl\qopenglwidget

Вот простейший пример, который загружает сферу из obj-файла и выводит на экран. Посмотрите, как матрицы передаются в шейдер:

Scene.h
Код:
#ifndef SCENE_H
#define SCENE_H

#include <QOpenGLWidget>
#include <QMatrix4x4>
#include <QMouseEvent>
#include <QWheelEvent>
#include "Sphere.h"

class Scene : public QOpenGLWidget
{
public:
    Scene( QWidget *parent );
    ~Scene();

private:
    void initializeGL();
    void paintGL();
    void resizeGL( int w, int h );

    void mousePressEvent( QMouseEvent *event );
    void mouseMoveEvent( QMouseEvent *event );

    QPoint m_lastPos;

    void setXRotation( int angle );
    void setYRotation( int angle );
    void setZRotation( int angle );

    int m_xRot;
    int m_yRot;
    int m_zRot;

    void wheelEvent( QWheelEvent *event );

    void scalePlus();
    void scaleMinus();

    float m_scale;

    QOpenGLShaderProgram m_program;
    int m_vertexAttrLoc;
    int m_colorAttrLoc;
    int m_normalAttrLoc;

    QMatrix4x4 m_worldMatrix;
    QMatrix4x4 m_projectionMatrix;
    QMatrix4x4 m_cameraMatrix;

    int m_modelViewMatrixLoc;
    int m_projectionMatrixLoc;
    int m_normalMatrixLoc;
    int m_cameraPosLoc;

    int m_lightPosLoc;

    Sphere *m_sphere;
};

#endif // SCENE_H
8Observer8 вне форума Ответить с цитированием
Старый 18.03.2015, 19:22   #3
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Scene.cpp
Код:
#include "Scene.h"
#include "LoaderOfSphere.h"
#include <QDir>

Scene::Scene( QWidget *parent ) :
    QOpenGLWidget( parent ),
    m_xRot( 0 ),
    m_yRot( 0 ),
    m_zRot( 0 ),
    m_scale( 1.0f ),
    m_sphere( 0 )
{

}

Scene::~Scene()
{
    delete m_sphere;
}

void Scene::initializeGL()
{
    glClearColor( 0.1f, 0.1f, 0.2f, 1.0f );
    glEnable( GL_DEPTH_TEST );

    QString path =  QDir::currentPath() + QString( "/Models/ColorSphere.obj" );
    LoaderOfSphere loader( path );
    if ( !loader.isSuccessfully )
        return;

    QOpenGLShader vShader( QOpenGLShader::Vertex );
    vShader.compileSourceFile( ":/Shaders/vShader.glsl" );

    QOpenGLShader fShader( QOpenGLShader::Fragment );
    fShader.compileSourceFile( ":/Shaders/fShader.glsl" );

    m_program.addShader( &vShader );
    m_program.addShader( &fShader );
    if ( !m_program.link() )
        return;

    m_vertexAttrLoc = m_program.attributeLocation( "vertexAttr" );
    m_colorAttrLoc = m_program.attributeLocation( "colorAttr" );
    m_normalAttrLoc = m_program.attributeLocation( "normalAttr" );

    m_sphere = new Sphere( &m_program, m_vertexAttrLoc, m_colorAttrLoc, m_normalAttrLoc );
    m_sphere->fillFromLoader( &loader );

    m_modelViewMatrixLoc = m_program.uniformLocation( "modelViewMatrix" );
    m_projectionMatrixLoc = m_program.uniformLocation( "projectionMatrix" );
    m_normalMatrixLoc = m_program.uniformLocation( "normalMatrix" );

    m_cameraMatrix.setToIdentity();
    QVector3D cameraPos( 0.0f, 0.0f, -3.0f );
    m_cameraMatrix.translate( cameraPos );

    m_program.bind();
    m_cameraPosLoc = m_program.uniformLocation( "cameraPos" );
    m_program.setUniformValue( m_cameraPosLoc, QVector3D( 0.0f, 0.0f, 3.0f ) );

    m_lightPosLoc = m_program.uniformLocation( "lightPos" );
    m_program.setUniformValue( m_lightPosLoc, QVector3D( 30.0f, 30.0f, 30.0f ) );
    m_program.release();
}

void Scene::paintGL()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    if ( !m_program.bind() )
        return;

    // Set ModelView Matrix
    m_worldMatrix.setToIdentity();
    m_worldMatrix.rotate( 180.0f - ( float ( m_xRot ) / 16.0f ), 1.0f, 0.0f, 0.0f );
    m_worldMatrix.rotate( float ( m_yRot ) / 16.0f, 0.0f, 1.0f, 0.0f );
    m_worldMatrix.rotate( float( m_zRot ) / 16.0f, 0.0f, 0.0f, 1.0f );
    m_worldMatrix.scale( m_scale );
    m_program.setUniformValue( m_modelViewMatrixLoc,
                               m_cameraMatrix * m_worldMatrix );

    // Set Projection Matrix
    m_program.setUniformValue( m_projectionMatrixLoc, m_projectionMatrix );

    // Set Normal Matrix
    QMatrix3x3 normalMatrix = m_worldMatrix.normalMatrix();
    m_program.setUniformValue( m_normalMatrixLoc, normalMatrix );

    if ( m_sphere != 0 )
        m_sphere->draw();

    m_program.release();
}

void Scene::resizeGL( int w, int h )
{
    glViewport( 0, 0, w, h );

    if ( h == 0 )
        h = 1;

    m_projectionMatrix.setToIdentity();
    m_projectionMatrix.perspective( 50.0f, float( w ) / float( h ), 0.01f, 1000.0f );
}

void Scene::mousePressEvent( QMouseEvent *event )
{
    m_lastPos = event->pos();
}

void Scene::mouseMoveEvent( QMouseEvent *event )
{
    int dx = event->x() - m_lastPos.x();
    int dy = event->y() - m_lastPos.y();

    if ( event->buttons() & Qt::LeftButton )
    {
        setXRotation( m_xRot + 8 * dy );
        setYRotation( m_yRot + 8 * dx );
    }
    else if ( event->buttons() & Qt::RightButton )
    {
        setXRotation( m_xRot + 8 * dy );
        setZRotation( m_zRot + 8 * dx );
    }

    m_lastPos = event->pos();
}

static void qNormalizeAngle( int angle )
{
    while ( angle < 0 )
        angle += 360 * 16;

    while ( angle > 360 * 16 )
        angle -= 360 * 16;
}

void Scene::setXRotation( int angle )
{
    qNormalizeAngle( angle );

    if ( angle != m_xRot )
    {
        m_xRot = angle;
        update();
    }
}

void Scene::setYRotation( int angle )
{
    qNormalizeAngle( angle );

    if ( angle != m_yRot )
    {
        m_yRot = angle;
        update();
    }
}

void Scene::setZRotation( int angle )
{
    qNormalizeAngle( angle );

    if ( angle != m_zRot )
    {
        m_zRot = angle;
        update();
    }
}

void Scene::wheelEvent( QWheelEvent *event )
{
    if ( event->delta() > 0 )
        scalePlus();
    else if ( event->delta() < 0 )
        scaleMinus();

    update();
}

void Scene::scalePlus()
{
    m_scale *= 1.1f;
}

void Scene::scaleMinus()
{
    m_scale /= 1.1f;
}
8Observer8 вне форума Ответить с цитированием
Старый 18.03.2015, 19:23   #4
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

vShader.glsl
Код:

attribute highp vec4 vertexAttr;
attribute highp vec4 colorAttr;
attribute highp vec3 normalAttr;

uniform highp mat4 modelViewMatrix;
uniform highp mat4 projectionMatrix;
uniform highp mat3 normalMatrix;

varying highp vec3 vertex;
varying highp vec4 color;
varying highp vec3 normal;

void main()
{
    gl_Position = projectionMatrix * modelViewMatrix * vertexAttr;

    vertex = vertex.xyz;
    color = colorAttr;
    normal = normalMatrix * normalAttr;
}
fShader.glsl
Код:
uniform highp vec3 lightPos;
uniform highp vec3 cameraPos;

varying highp vec3 vertex;
varying highp vec4 color;
varying highp vec3 normal;

void main()
{
    highp vec3 normalizedLightVector = normalize( lightPos - vertex );
    highp vec3 normalizedNormalVector = normalize( normal );
    highp float diffuse = max( dot( normalizedNormalVector,
                                    normalizedLightVector ), 0.0 );

    highp vec3 normalizedCameraPosVector = normalize( cameraPos - vertex );
    highp vec3 reflectVector = reflect( -normalizedLightVector, normalizedNormalVector );
    float specular = pow( max( dot( normalizedCameraPosVector, reflectVector ), 0.0 ), 40.0 );

    highp vec3 colorRGB = color.rgb;

    highp vec3 resultColor = clamp( colorRGB * 0.2 + colorRGB * 0.8 * diffuse + colorRGB * 0.4 * specular, 0.0, 1.0 );

    // Определяем вектор белого цвета
    highp vec4 one = vec4( 1.0, 1.0, 1.0, 1.0 );

    gl_FragColor = vec4( resultColor, 1.0 ) * one;
}
8Observer8 вне форума Ответить с цитированием
Старый 18.03.2015, 19:24   #5
8Observer8
Старожил
 
Аватар для 8Observer8
 
Регистрация: 02.01.2011
Сообщений: 3,322
По умолчанию

Прикрепил архив с проектом
Вложения
Тип файла: zip ColorSphere.zip (34.3 Кб, 22 просмотров)
8Observer8 вне форума Ответить с цитированием
Старый 18.03.2015, 21:41   #6
wf778899
 
Регистрация: 11.03.2015
Сообщений: 5
По умолчанию

Мне просто важно разобраться, как это делается чисто средствами openGL, без надстроек Qt. А так пример хороший, спасибо, разберу. Ждите вопросов))
wf778899 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
OpenGL4.3 в Qt5.1 - подключение функций wf778899 Qt и кроссплатформенное программирование С/С++ 5 13.03.2015 23:42
Передача данных обьектов между 2-мя формами, через переменную Человек_Борща Общие вопросы Delphi 5 07.06.2012 03:32
передача имени массива в переменную процедуры KORT Общие вопросы Delphi 3 14.11.2011 15:22
.bat файлы; передача значения из файла в переменную Manik Помощь студентам 1 06.05.2010 10:36
Передача выражения функции (string) в переменную real Vohakisa Помощь студентам 3 12.05.2009 01:57