axe_lankaster13
@axe_lankaster13
Танцор с бубном над клавиатурой

Не отрисовывается OpenGL в программе при запуске из QtCreator'а и на другом компьютере, но отрисовывается при запуске из «Проводника» — Почему?

Пытаюсь работать с OpenGL через QOpenGLWidget и QOpenGLFunctions_3_3_core - написал небольшую тестовую программу. При запуске из QtCreator'а и с чужого компьютера выводятся окошко и не закрашенный прямоугольник, и он не "мигает", как должен по программе:
Некорректный результат

6016824d9d982785684094.png

При запуске же на моём компьютере из "проводника", программа работает так, как надо - выводится "мигающий"(картинка не gif, так что не видно, но оно так) градиент:
Корректный результат

60168256836aa042464244.png

Ситуация одинакова как для Debug сборки, так и для Release.
Как понимаю, не хватает каких-то .dll файлов, но абсолютно без понятия, каких именно.
Всё, что собрали QtCreator и windeployqt.exe:
Файлы

6016808d0d714785789042.png

На всякий случай, загрузил сюда .pro-файл и весь код widget'а, использующего OpenGL.
.pro-файл

QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17

SOURCES += \
GL/Program.cpp \
GL/VAO.cpp \
main.cpp \
mainwindow.cpp \
menubar.cpp \
oglwidget.cpp \
statusbar.cpp
INCLUDEPATH += \
C:/_LIBS/glm.0.9.9.800/build/native/include
HEADERS += \
GL/Program.h \
GL/VAO.h \
mainwindow.h \
menubar.h \
oglwidget.h \
statusbar.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

DISTFILES += \
res/glsl/first.frag \
res/glsl/first.vert

OGLWidget.h

#pragma once
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <glm/glm.hpp>
#include "GL/Program.h"
#include "GL/VAO.h"

class OGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int width, int height) override;
private:
    GL::VAO* _current_vao;
    GL::Program* _current_program;
    float _uniform;
    void clear_color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 1.0);
public:
    OGLWidget(QWidget* parent = nullptr);
    ~OGLWidget();
    void timerEvent(QTimerEvent*) override;
public slots:
};


OGLWidget.cpp

#include "oglwidget.h"
OGLWidget::OGLWidget(QWidget* parent)
    : QOpenGLWidget(parent)
{
    _uniform = 0.0f;
    this->startTimer(10);
}
OGLWidget::~OGLWidget()
{
    delete _current_vao;
    delete _current_program;
}
void OGLWidget::initializeGL()
{
    if(!initializeOpenGLFunctions())
    {
        throw std::runtime_error("Could not initialize QOpenGLFunctions!");
    }
    auto* functions = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    _current_vao = new GL::VAO(functions);
    _current_program = new GL::Program(functions, "first");
    //Vertices
    _current_vao->add_VBO(
    {
        {-0.5f,  0.5f, 0.f},
        {-0.5f, -0.5f, 0.f},
        { 0.5f,  0.5f, 0.f},
        { 0.5f, -0.5f, 0.f},
    });
    _current_vao->add_vertices(
    {
        0, 1, 2,
        2, 1, 3
    });
    //Colors
    _current_vao->add_VBO(
    {
        { 1, 0, 0},
        { 0, 0, 1},
        { 0, 1, 0},
        { 1, 0, 0},
    });

    _current_program->bind_attribute(0, "position");
    _current_program->bind_attribute(1, "color");
    _current_program->link();
    _current_program->use();
}
void OGLWidget::resizeGL(int width, int height)
{
    glViewport(0, 0, width, height);
}
void OGLWidget::paintGL()
{
    _uniform += 0.05f;
    _current_program->set_float("animation", glm::sin(_uniform) * 0.5f + 0.5f);
    clear_color(50, 50, 50);
    glClear(GL_COLOR_BUFFER_BIT);
    _current_vao->draw(GL_TRIANGLES);
}
void OGLWidget::timerEvent(QTimerEvent*)
{
    repaint();
}
void OGLWidget::clear_color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha)
{
    glClearColor((GLclampf)(red / 255.0),
                 (GLclampf)(green / 255.0),
                 (GLclampf)(blue / 255.0),
                 (GLclampf)(alpha / 255.0));
}


GL/Program.h

#pragma once
#include <string>
#include <QOpenGLFunctions_3_3_Core>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
namespace GL
{
    class Program
    {
    private:
        QOpenGLFunctions_3_3_Core* _functions;
        GLuint _program;
        GLuint _vertex_shader;
        GLuint _fragment_shader;
        GLint get_location(const std::string &name);
        GLuint load_shader(const std::string &path, GLenum shader_type);
    public:
        Program(QOpenGLFunctions_3_3_Core* functions, const std::string &name);
        ~Program();
        void link();
        void bind_attribute(GLuint index, const std::string &name);
        void use();
        void set_float(const std::string &name, const float &value);
        void set_matrix(const std::string &name, const glm::mat4 &matrix);
    };
}


GL/Program.cpp

#include "Program.h"
#include <iostream>
#include <fstream>

GL::Program::Program(QOpenGLFunctions_3_3_Core* functions, const std::string &name)
{
    _functions = functions;
    _program = _functions->glCreateProgram();
    _vertex_shader = load_shader("res/glsl/" + name + ".vert", GL_VERTEX_SHADER);
    _fragment_shader = load_shader("res/glsl/" + name + ".frag", GL_FRAGMENT_SHADER);
    if (_vertex_shader == 0 || _fragment_shader == 0)
    {
        throw std::runtime_error("Failed to create shaders!");
    }
}

GL::Program::~Program()
{
    _functions->glDetachShader(_program, _vertex_shader);
    _functions->glDetachShader(_program, _fragment_shader);
    _functions->glDeleteShader(_vertex_shader);
    _functions->glDeleteShader(_fragment_shader);
    _functions->glDeleteProgram(_program);
}

void GL::Program::link()
{
    _functions->glAttachShader(_program, _vertex_shader);
    _functions->glAttachShader(_program, _fragment_shader);
    _functions->glLinkProgram(_program);
}

void GL::Program::bind_attribute(GLuint index, const std::string &name)
{
    _functions->glBindAttribLocation(_program, index, name.c_str());
}

void GL::Program::use()
{
    _functions->glUseProgram(_program);
}

void GL::Program::set_float(const std::string &name, const float &value)
{
    _functions->glUniform1f(get_location(name), value);
}

void GL::Program::set_matrix(const std::string &name, const glm::mat4 &matrix)
{
    _functions->glUniformMatrix4fv(get_location(name), 1, GL_FALSE, glm::value_ptr(matrix));
}

GLint GL::Program::get_location(const std::string &name)
{
    return _functions->glGetUniformLocation(_program, name.c_str());
}

GLuint GL::Program::load_shader(const std::string &path, GLenum shader_type)
{
    GLuint shader = _functions->glCreateShader(shader_type);
    std::ifstream fis(path);
    std::string shaderCode = {std::istreambuf_iterator<char>(fis), std::istreambuf_iterator<char>()};
    const char *c = shaderCode.c_str();
    _functions->glShaderSource(shader, 1, &c, nullptr);

    GLint status;
    _functions->glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    char buf[0x1000];
    GLsizei length;
    _functions->glGetShaderInfoLog(shader, sizeof(buf), &length, buf);
    if (length > 0)
    {
        std::cerr << "Failed to comile shader " << path << std::endl << buf << std::endl;
        return 0;
    }
    return shader;
}

  • Вопрос задан
  • 66 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы