簡體   English   中英

OpenGL + GLSL 集成的 Qt 程序在運行時立即崩潰

[英]Qt program with OpenGL + GLSL integration crashes immediately in run-time

我是 OpenGL 和 GLSL 的新手。 我正在嘗試使用 Qt Creator 中的這些庫編寫第一個程序,該程序將在QOpenGLWindow window 中繪制一個普通的矩形。 編譯成功實現,但是程序在嘗試運行時立即崩潰,並出現以下錯誤 output:

Running /home/andrey/build-opengl_glsl-Desktop-Debug/opengl_glsl ...
The program has suddenly terminated.
The process was terminated forcibly.
/home/andrey/build-opengl_glsl-Desktop-Debug/opengl_glsl has crashed.

我使用 Ubuntu 20.04、QtCreator 4.11 和 OpenGL ES 2.0(因為此版本由QOpenGLFunctions類使用)。

編碼:

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QOpenGLWindow>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>

class GLWindow : public QOpenGLWindow, protected QOpenGLFunctions
{
    Q_OBJECT
public:
GLWindow(QWindow *parent = nullptr, QString vertex_shader_p = "", QString 
    fragment_shader_p = "");

protected:
    virtual void initializeGL() override;
    virtual void paintGL() override;
    virtual void resizeGL(GLint w, GLint h) override;

    QOpenGLContext *m_context;
    QString vertex_shader_path;
    QString fragment_shader_path;
    GLint shaderProgramID;
};
#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

GLWindow::GLWindow(QWindow *parent, QString vertex_shader_p, QString 
    fragment_shader_p)
: QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent),
vertex_shader_path(vertex_shader_p),
fragment_shader_path(fragment_shader_p)
{
    setSurfaceType(OpenGLSurface);
    create();

    m_context = new QOpenGLContext;
    m_context->create();

    initializeGL();

    GLfloat vertices[] = {
        -0.5f, -0.5f, 0.0f,     // Lower left vertex
        0.5f, -0.5f, 0.0f,      // Lower right vertex
        0.5f, 0.5f, 0.0f,       // Upper right vertex
       -0.5f, 0.5f, 0.0f        // Upper left vertex
    };

    GLuint indices[] = {
        0, 1, 3,                // Lower triangle
        3, 2, 1                 // Upper triangle
    };

    GLuint vbo, ebo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    QString vertex_shader_code;
    QString fragment_shader_code;
    string vsc_to_stdstr = vertex_shader_code.toStdString();
    string fsc_to_stdstr = fragment_shader_code.toStdString();

    ifstream inf;
    inf.exceptions(ifstream::failbit | ifstream::badbit);

    try
    {
        stringstream shadercodestream;

        inf.open(vertex_shader_path.toStdString());
        shadercodestream << inf.rdbuf();
        inf.close();
        vsc_to_stdstr = shadercodestream.str();
        shadercodestream.str("");

        inf.open(fragment_shader_path.toStdString());
        shadercodestream << inf.rdbuf();
        inf.close();
        fsc_to_stdstr = shadercodestream.str();
        shadercodestream.str("");
    }
    catch (ifstream::failure& e)
    {
        std::cout << e.what() << std::endl;
    }

    const GLchar* vsc_to_cstr = vsc_to_stdstr.c_str();
    const GLchar* fsc_to_cstr = fsc_to_stdstr.c_str();

    GLint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShaderID, 1, &vsc_to_cstr, nullptr);
    glCompileShader(vertexShaderID);

    GLint success;
    GLchar infoLog[512];
    glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShaderID, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    GLint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShaderID, 1, &fsc_to_cstr, nullptr);
    glCompileShader(fragmentShaderID);

    glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShaderID, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }

    shaderProgramID = glCreateProgram();
    glAttachShader(shaderProgramID, vertexShaderID);
    glAttachShader(shaderProgramID, fragmentShaderID);
    glLinkProgram(shaderProgramID);

    glGetProgramiv(shaderProgramID, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgramID, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    glDeleteShader(vertexShaderID);
    glDeleteShader(fragmentShaderID);

    paintGL();
}

void GLWindow::initializeGL()
{
    m_context->makeCurrent(this);
    initializeOpenGLFunctions();
}

void GLWindow::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shaderProgramID);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}

void GLWindow::resizeGL(GLint w, GLint h)
{
    glViewport(0, 0, w, h);
}

主文件

#include "mainwindow.h"
#include <iostream>

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    GLWindow w(nullptr, 
    "/home/andrey/programs/cpp/opengl/opengl_glsl/vertex_shader.glsl",
           "/home/andrey/programs/cpp/opengl/opengl_glsl/fragment_shader.glsl");

    w.show();

    return a.exec();

}

vertex_shader.glsl

#version 450 core

layout (location = 0) in vec3 vpos;
out vec3 new_pos;

void main()
{
    gl_Position = vec4(vpos.x, vpos.y, vpos.z, 1.0);
    new_pos = vpos;
} 

片段着色器.glsl

#version 450 core

in vec3 new_pos;
out vec4 color;
vec3 nmlzed_pos;

void main()
{
    nmlzed_pos = normalize(new_pos);
    color = vec4(nmlzed_pos.xyz, 1.0);
}

.pro

QT += opengl core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs 
deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp \

HEADERS += \
    mainwindow.h \

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

我還嘗試使用 GDB 在調試模式下運行程序,看起來這在GLWindow::initializeGL()方法中的initializeOpenGLFucntions()調用上崩潰了。

根據評論...

基本解決方法是將所有初始化代碼移至initializeGL並讓Qt OpenGL框架對initializeGLpaintGL等進行必要的調用。

您的構造函數和initializeGL成員應類似於...

GLWindow::GLWindow(QWindow *parent, QString vertex_shader_p,
                   QString fragment_shader_p)
  : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate, parent)
  , vertex_shader_path(vertex_shader_p)
  , fragment_shader_path(fragment_shader_p)
{
}

void GLWindow::initializeGL()
{
  initializeOpenGLFunctions();
  GLfloat vertices[] = {
    -0.5f, -0.5f, 0.0f,     // Lower left vertex
    0.5f, -0.5f, 0.0f,      // Lower right vertex
    0.5f, 0.5f, 0.0f,       // Upper right vertex
    -0.5f, 0.5f, 0.0f        // Upper left vertex
  };

  GLuint indices[] = {
    0, 1, 3,                // Lower triangle
    3, 2, 1                 // Upper triangle
  };

  GLuint vbo, ebo;
  glGenBuffers(1, &vbo);
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

  glGenBuffers(1, &ebo);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
  glEnableVertexAttribArray(0);

  QString vertex_shader_code;
  QString fragment_shader_code;
  string vsc_to_stdstr = vertex_shader_code.toStdString();
  string fsc_to_stdstr = fragment_shader_code.toStdString();

  ifstream inf;
  inf.exceptions(ifstream::failbit | ifstream::badbit);

  try
  {
    stringstream shadercodestream;

    inf.open(vertex_shader_path.toStdString());
    shadercodestream << inf.rdbuf();
    inf.close();
    vsc_to_stdstr = shadercodestream.str();
    shadercodestream.str("");

    inf.open(fragment_shader_path.toStdString());
    shadercodestream << inf.rdbuf();
    inf.close();
    fsc_to_stdstr = shadercodestream.str();
    shadercodestream.str("");
  }
  catch (ifstream::failure& e)
  {
    std::cout << e.what() << std::endl;
  }

  const GLchar* vsc_to_cstr = vsc_to_stdstr.c_str();
  const GLchar* fsc_to_cstr = fsc_to_stdstr.c_str();

  GLint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
  glShaderSource(vertexShaderID, 1, &vsc_to_cstr, nullptr);
  glCompileShader(vertexShaderID);

  GLint success;
  GLchar infoLog[512];
  glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &success);
  if (!success)
  {
    glGetShaderInfoLog(vertexShaderID, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
  }

  GLint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
  glShaderSource(fragmentShaderID, 1, &fsc_to_cstr, nullptr);
  glCompileShader(fragmentShaderID);

  glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &success);
  if (!success)
  {
    glGetShaderInfoLog(fragmentShaderID, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
  }

  shaderProgramID = glCreateProgram();
  glAttachShader(shaderProgramID, vertexShaderID);
  glAttachShader(shaderProgramID, fragmentShaderID);
  glLinkProgram(shaderProgramID);

  glGetProgramiv(shaderProgramID, GL_LINK_STATUS, &success);
  if (!success) {
    glGetProgramInfoLog(shaderProgramID, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
  }

  glDeleteShader(vertexShaderID);
  glDeleteShader(fragmentShaderID);
}

使用上面的代碼進行快速測試會導致...

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM